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. So is the parser that breaks when a page changes, the retry logic nobody documented and the proxy blocked on a Friday. Then comes 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 on the row, and the output is a typed cell. 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
Each example is a request in plain words, with what it returns underneath.
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
Vendors land as rows with the fields you name, not in a file, so enrichment can start on the same pass.
Watch a page for changes
check these competitor changelogs every week and flag anything that mentions an integration
A weekly full refresh rereads every page. Each cell's history keeps last week's value beside the new one, with the run that wrote it, so the change is easy to read.
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
Each account with a public pricing page gets a structured read of what that company charges.
- 1Find each domain's pricing URL with a Firecrawl column that lists the site's pages. Then add a scrape column on that URL and an extraction column for the fields you need.
- 2File the pattern you found as a knowledge page and map it into the extraction column, 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.
- 1Extract one row per listed company from the listing pages, 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 search runRescrape on a schedule
A page you care about is reread on a cadence and the difference is visible on the row.
- 1Schedule the column as a full refresh, since a schedule fills only empty or failed cells by default. Give it a credit ceiling per run 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 follow-up.
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 again.
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
Data sources and CRM connections
FirecrawlThe 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
On your own Linkup key, a fetch to clean markdown. Pick it by name when the Firecrawl read of a page comes back with nothing usable.
ExaA second way to read a page: Exa serves it from its own cache and crawls live only when needed, so it can answer where a live fetch is blocked.
Use managed credits where available, or connect a supported provider key on an eligible paid plan. Your provider bills its calls; OXYGEN adds a per-call platform fee. Signed-in CRM connections such as HubSpot have no per-call fee. Connected sending accounts reserve monthly credits. See pricing and supported integrations.
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?
Try Tables in 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.