Skip to main content
Add outputs=tables to a Fetch request and Zenrows returns every table on the page as JSON rows keyed by column heading. A few lines of Python or Node.js turn those rows into CSV files you can open in a spreadsheet. The same parameter returns links, headings, images and metadata, so one request gives you the page’s structure with no selectors to write. This uses Fetch’s outputs parameter, not Extract’s extract=auto. Uses: Fetch with outputs and Adaptive Stealth Mode (mode=auto)

Ask your AI agent

With the Zenrows MCP server connected to Claude, Cursor or any MCP client, paste this prompt. Your agent picks the right Zenrows tools and settings on its own.
The same prompt works across hundreds of pages: list the URLs and ask for “every table from each page, as CSV”. outputs takes a comma-separated list. This request asks for tables, links, headings, images and metadata at once. The response is JSON with one key per filter.
In the CLI, zenrows extract --outputs sends the outputs parameter, see the CLI guide. The response is JSON with one key per filter, and a filter with nothing to return on a page, such as metadata here, is left out. Each table carries Dimensions (row and column counts, and whether it has a header row), Headings (the column names in page order) and Content (one object per row keyed by heading). See the returned table in Get common data with outputs.

Save every table as CSV

Loop over tables, skip layout tables that have no header row, and write each data table to its own file. Using Headings as the column order keeps the columns as they appear on the page.

Example output

The script prints one line per saved file and writes the table with its page column order:
Output (Python)
table-1.csv (first rows)

Pages with many tables

The same script handles pages with dozens of tables. Pointed at https://en.wikipedia.org/wiki/List_of_tallest_buildings, it skips the legend and navigation tables and saves each data table:
Output (Python, trimmed)
A table without a header row comes back with "Headings": false in Dimensions and generic keys such as column_1, column_2. Keep those too when you want them: drop the Headings check. outputs=links returns every href on the page, as written in the HTML: relative paths, # anchors and repeats included. Resolve each against the page URL, drop the fragment and deduplicate. Here the catalog page’s 59 links become 29 unique URLs.
Output (Python, trimmed)
metadata returns each <meta> tag as a name: content string. Split on the first : to get a dictionary.

Customize it

Troubleshooting

  • tables is missing from the response: the page has no <table> elements in its final HTML. Data shown in a grid of <div>s is read with css_extractor instead.
  • A CSV has columns named column_1, column_2: that table has no header row. Rename the columns in your script, or skip it with the Headings check above.
  • A table repeats a column heading, such as two “Height” columns in different units: rows are keyed by heading. Read that table with css_extractor to get every column by position.
  • Links look like /cart/ or #content: links returns each href as written. Resolve them against the page URL as shown in Turn links into a clean list.
  • The request takes long to return: set your HTTP client timeout to 180 seconds or more so mode=auto has time to escalate.

Extract data with CSS selectors

Pick exact elements and attributes with css_extractor.

Validate extracted data with a schema

Turn price strings into numbers and Yes/No into booleans.

Map every URL on a website

Collect every page URL of a site with Crawl.

Turn search and listing pages into JSON

Get every item on search and category pages as JSON.