Public web into rows
Scrape the web into typed rows, not a CSV dump
Scraping is only a problem because of what happens after it. Here a scrape is a column on a table: one row per page, one cell per field, with retries and errors visible instead of buried in a log.
The scraper is rarely the hard part. Hosting it is, and so is the parser that breaks when a page changes, the retry logic nobody documented, the proxy that gets blocked on a Friday, and the question of where the output goes once it finally exists.
A scrape here is a tool column. The input is a URL or a domain already sitting on the row, the output is a typed cell, and the run state belongs to the table: which pages failed, what each one drew, and what the extractor actually saw. Rerunning just the failures is one action rather than a script.
Example searches
Ask for it the way you'd say it
Every search below runs on the same hosted Tables, with the cost previewed before anything is spent.
Read a page per account
open each company's pricing page and tell me whether they publish a price at all
One cell per row holds the answer and the page it came from, so a wrong extraction stays checkable.
Turn a directory into rows
crawl this marketplace listing and give me every vendor with a website and a category
A crawl writes rows rather than a file, so enrichment can start on the same pass that found them.
Watch a page for changes
check these competitor changelogs every week and flag anything that mentions an integration
A scheduled rerun leaves last week's value on the cell with the run that wrote it, so the difference is readable.
Plays
Three motions you can run this week
Each one is a chain of Oxygen primitives — the same hosted objects your workspace already has, composed.
Pricing pages into a comparison column
Every account in the table carries a structured read of what that company publicly charges.
- 1Add a scrape column keyed on the domain, then an extraction column that pulls the fields you need.
- 2File the pattern you found as workspace knowledge so later runs read it instead of rediscovering it.
oxygen columns addA public directory becomes a table
A listing of companies turns into rows you can enrich, score, and eventually promote.
- 1Crawl the listing pages into rows, then collapse on domain before spending anything on them.
- 2Promote the ones that clear your filters and leave the rest as a table you can revisit.
oxygen tables dedupeRescrape on a schedule
A page you care about is reread on a cadence and the difference is visible on the row.
- 1Schedule the column with a per-delivery ceiling so a large table cannot surprise the balance.
- 2Compare the new cell against the run before it, then let a workflow read the table and decide whether the change deserves a message.
oxygen tables schedule set
Capabilities
What you get
No crawler to operate
Fetching, retries, and blocking are the provider's problem. What you configure is the input column, the extraction shape, and the ceiling on the run.
Failures you can see and retry
A page that did not load leaves an error on its own cell. Running the column again over just those rows is one scoped command, and the rows that already answered are left alone.
Extraction as a typed column
The output has the shape you declared, so downstream columns and filters rely on it instead of parsing free text for a second time.
Scrapes that feed the rest
Because the result is a cell on a row, scoring, enrichment, and enrollment read it directly. There is no handoff file between the scrape and the campaign.
Boundaries
What Tables does not own
Scraping is a Tables column, not an orchestration engine. Scheduling, branching, and retries across many steps belong to Workflows. A page change you want to act on later is a value you compare between runs, and the run history that makes that possible is Tables.
Data sources
What the data actually comes from
Every value lands with its provider and cost recorded on the cell.

Firecrawl
The workhorse for a page or a whole site: one URL in, structured content out, plus the crawl and batch paths when a traversal is genuinely needed.
Linkup
A cheap managed fetch to clean markdown, and the second lane when the first one comes back with nothing usable.

Exa
A different fetch substrate, a cached index with a live crawl behind it, which is why it answers on pages where the live fetchers are blocked.
Run these on Oxygen's managed credits, or connect your own provider keys and pay the vendor directly — the same columns, the same runs, the same provenance either way. See every integration.
Limits
Where this stops
- Public pages change without warning and some sites decline to be read at all. Treat an empty cell as a fact about the page, and check a sample by hand before trusting a field across thousands of rows.
FAQ
Questions people ask first
Do I need to host anything?
What happens when a page fails to load?
Can I crawl an entire site?
Is the output free text or structured?
How is a scrape priced?
Is scraping allowed?
Run scrape the web into typed rows, not a csv dump on your own workspace
Sign up, get a working workspace with a one-time credit grant, and run the first play from the web app, the CLI, or your AI assistant over MCP.