dltComing soon
Load the live web data SpecStream finds into any dlt destination: your lists, their records, and one row per value with the page it was read from and when. The pipeline is a single Python file built on dlt's REST API source.
SpecStream for dltData & warehousesWhat you need
- A SpecStream account, free to open.
- Python with dlt. The example loads into DuckDB, which needs no server.
- A SpecStream API key, which step 1 creates.
- 1
1. Create an API key
In the SpecStream workspace, go to Agents & API and choose API keys, then Create API key. The pipeline never spends, so read permission and a $0 spending limit are enough.
The key is shown once, so copy it before you move on.
- 2
2. Install dlt
Install dlt with the DuckDB extra. For BigQuery, Snowflake, Postgres, or another destination, install the extra for that destination instead.
Terminal - 3
3. Save the pipeline
listspages through your lists, newest first, andrecordsreads each list's rows.shape_recordturns each row into a record with one cell per value.Save the file below as
specstream_pipeline.py. It's also in the dlt example (opens in a new tab) in specstream-tools.specstream_pipeline.py - 4
4. Set your key and run it
dlt reads the key from the
SOURCES__SPECSTREAM__API_KEYenvironment variable. When the run finishes, the script prints the load summary.Terminal - 5
5. Query the values
Each value is a row in
records__cells. Join it to its record with_dlt_parent_id, which matches the record's_dlt_id. The example's dataset isspecstream_data.SQL
Tables
These tables land in your dataset, and each run adds to them.
| Table | One row per | Columns |
|---|---|---|
lists | List | id, name, kind, created_at, row_count |
records | Record | list_id, record_id, list_created_at, entity_id |
records__cells | Value | column_id, label, value, source_url, observed_at |
Values and sources
entity_id is shared by every record about the same company, place, person, or posting, which lets you join between lists. A value SpecStream couldn't read loads as null.
Rows of a list you imported carry the columns you provided and no source page. A combined list loads the value it shows.
Later runs
lists is incremental on created_at, so each run loads only the lists created since the last run. Records a SpecStream schedule refreshes come in as a new list, so the next run picks them up. Both lists and records merge on a primary key, so running the pipeline again doesn't duplicate rows.
The first run starts at 2020-01-01T00:00:00+00:00. To begin later, pass start_date, for example specstream_source(start_date="2026-01-01T00:00:00+00:00"). Run the script on whatever scheduler you already use for your other pipelines.
Load somewhere else
Change destination in dlt.pipeline(...) to "bigquery", "snowflake", "postgres", or any other destination dlt supports, and add that destination's credentials the way dlt's docs (opens in a new tab) describe. The key stays the only SpecStream setting.
Cost
Running the pipeline doesn't touch your SpecStream balance. It reads lists that already exist and starts no request. The balance pays when you ask SpecStream for data, per result that matches. Prices and quotes are covered in balance, quotes, and billing.
Disconnect
Stop running the script and remove the environment variable. Revoke the key under Agents & API to end access immediately. Tables already in your destination stay as they are. Questions go to [email protected], and Connect your tools lists the other connections.
More
SpecStream for dlt covers what it does in dlt on one page. Every other tool has its guide in Connect your tools. You see the most a request can cost before it starts, and only the matches come out of your balance. Billing has the details. For help, email [email protected].