By output · Website to CSV
Scrape website to CSV: a website to CSV converter with Excel export
The short answer
To scrape a website to CSV, extract the page against a schema that describes one row, then write the resulting records to a CSV file. ClawEngine returns typed JSON rather than a CSV file directly, because a spreadsheet has no way to express a nested field or a failed extraction. Getting from that JSON to a .csv is three lines in Python or Node, shown below, and it keeps the header stable even when a page is missing a value. Point it at one listing page or crawl a whole site and every row comes back in the same shape. Public, permitted pages only. Plans start at $39 a month.
Clean markdown & JSON · JavaScript rendered · robots.txt respected
Last updated August 2026
Hit Extract to turn this page into clean, LLM-ready data.
robots.txt respected · public data only
Most scraping jobs that end in a spreadsheet are really table jobs: a directory of vendors, a catalog of products, a page of listings. You do not want the article text, you want 200 rows with the same six columns, and you want row 199 to have the same columns as row 1 even though that one listing was missing a price.
That is the part hand-rolled scrapers get wrong. A selector that returns nothing writes an empty cell on a good day and shifts every column by one on a bad day. ClawEngine takes a schema instead: you name the fields and their types once, it renders the page, pulls each item, and returns a typed record per row. Missing values come back as nulls rather than as a broken layout. From there, csv.DictWriter or a two-line pandas call gives you a file that opens cleanly in Excel, Numbers or Google Sheets. Every request runs on public, permitted pages only, respects robots.txt and Terms of Service, and honors crawl-delay.
Any URL in LLM-ready data out
robots.txt respected public data only
Why it works
What you get with Website to CSV
One row per item
Describe a single row once and ClawEngine returns every item on the page in that exact shape, so your header never shifts and your columns always line up.
Typed, not stringly
A price comes back as a number and a date as a date, so totals and sorting work the moment the file opens instead of after a cleanup pass.
Rendered before extraction
Listings that build client-side are captured too, so you do not export an empty spreadsheet from a page that looks full in your browser.
What it handles
Any URL in, clean structured data out
Point ClawEngine at a public page and it crawls, renders the JavaScript and extracts clean markdown or typed JSON in one call. Define a schema for structured fields, and respect robots.txt and Terms of Service by default.
- Turns listing pages into spreadsheet rows
- Keeps one stable header across every page
- Returns typed numbers and dates, not strings
- Handles missing values as nulls, not shifted columns
- Crawls a whole site into one combined export
- Stays on public, permitted data only
{
"url": "https://example.com/products/atlas",
"title": "Atlas Field Notebook",
"markdown": "# Atlas Field Notebook\n\nDurable...",
"data": {
"name": "Atlas Field Notebook",
"price": 24.00,
"currency": "USD",
"rating": 4.7
},
"links": [ "/products", "/cart" ],
"metadata": { "rendered": true }
}
Why ClawEngine
One API that crawls, renders and extracts
Not a raw HTML dump, not a headless browser fleet to run, and not a brittle parser to maintain. One call crawls a public page, renders its JavaScript and returns clean markdown or typed JSON, built for RAG pipelines and AI agents.
LLM-ready output
Clean markdown or typed JSON with the boilerplate stripped, so the data drops straight into a vector store, a prompt or an agent without a cleanup step.
JavaScript rendered
Each page loads in a real browser environment before extraction, so single-page apps and client-rendered content come back complete, not as an empty shell.
Compliance-first
ClawEngine works on public, permitted data only. It respects robots.txt and site Terms of Service and honors crawl-delay, so responsible scraping is the default.
Code examples
From a listing page to a .csv file
The schema describes one row. The API returns typed records. csv.DictWriter turns them into a file that opens cleanly in Excel or Google Sheets, with a stable header even when an item is missing a value.
curl https://api.clawengine.ai/v1/extract \
-H "Authorization: Bearer $CLAWENGINE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/catalog",
"render": true,
"format": "json",
"schema": {
"items": [{
"name": "string",
"price": "number",
"sku": "string",
"in_stock": "boolean"
}]
}
}'
# Response
# { "items": [
# { "name": "Alpine Jacket", "price": 189.0, "sku": "AJ-01", "in_stock": true },
# { "name": "Trail Pant", "price": null, "sku": "TP-04", "in_stock": false }
# ] }
import csv, os, requests
FIELDS = ["name", "price", "sku", "in_stock"]
r = requests.post(
"https://api.clawengine.ai/v1/extract",
headers={"Authorization": f"Bearer {os.environ['CLAWENGINE_API_KEY']}"},
json={
"url": "https://example.com/catalog",
"render": True,
"format": "json",
"schema": {"items": [{f: "string" for f in FIELDS}]},
},
timeout=120,
)
r.raise_for_status()
rows = r.json()["items"]
with open("catalog.csv", "w", newline="", encoding="utf-8") as fh:
# restval keeps the header stable when an item is missing a field
w = csv.DictWriter(fh, fieldnames=FIELDS, restval="", extrasaction="ignore")
w.writeheader()
w.writerows(rows)
print(f"wrote {len(rows)} rows to catalog.csv")
import csv, os, requests
KEY = os.environ["CLAWENGINE_API_KEY"]
FIELDS = ["name", "price", "sku", "url"]
# One crawl job, many pages, same schema on every page.
job = requests.post(
"https://api.clawengine.ai/v1/crawl",
headers={"Authorization": f"Bearer {KEY}"},
json={
"url": "https://example.com/catalog",
"path_prefix": "/catalog/",
"max_pages": 400,
"render": True,
"schema": {"items": [{f: "string" for f in FIELDS}]},
},
timeout=600,
).json()
rows = [item for page in job["pages"] for item in page.get("items", [])]
with open("site-export.csv", "w", newline="", encoding="utf-8") as fh:
w = csv.DictWriter(fh, fieldnames=FIELDS, restval="", extrasaction="ignore")
w.writeheader()
w.writerows(rows)
print(f"{len(job['pages'])} pages, {len(rows)} rows")
People also ask
Scrape a website to CSV: the questions buyers ask
How do I scrape a website to CSV?
Define a schema describing one row, send the URL to an extraction API, and write the returned records to a file with csv.DictWriter. The schema is what makes this reliable: it fixes the column set up front, so a page missing one value produces a null in that cell rather than shifting every field after it. ClawEngine renders the page first, so client-side listings are included.
Can I convert a website table to CSV?
Yes, and an HTML table is the easiest case because the columns are already declared in the markup. Name the fields you want in your schema and each table row comes back as one record. The harder and more common case is a listing that only looks like a table, a grid of cards or repeated divs, where there is no thead to read. Schema extraction handles both the same way.
How do I scrape a website to Excel?
Write a CSV and open it in Excel, or write .xlsx directly with pandas and openpyxl if you need multiple sheets or real number formatting. CSV is usually the better default because it stays diff-friendly and imports into anything. Reach for xlsx when a human is the end consumer and you want frozen headers, column widths and a date column Excel will not silently reinterpret.
Why does my scraped CSV have shifted or misaligned columns?
Almost always because an item was missing a field and the scraper appended values positionally instead of by key. If a card has no price and your code does row.append(price_element.text) inside a try block that silently passes, every later column moves left by one. Writing dictionaries keyed by field name makes this impossible, which is why schema extraction and DictWriter fix it together.
Why is my exported CSV empty even though the page has data?
The page is almost certainly client-rendered and you fetched it without running its JavaScript. The rows you can see in your browser were built by a script after load, so they were never in the HTML your scraper parsed. Search the raw response for a value you can see on screen. If it is not there, you need rendering rather than a better selector.
How do I get all the results, not just the first page?
Follow the pagination rather than scraping the one URL you started from. Some sites use a page query parameter you can increment until a request returns zero items; others use infinite scroll backed by an API call you can hit directly. Crawling with a path prefix handles the first case. The second is usually easier and cheaper once you find the underlying request.
Why do numbers and dates break when I open the CSV in Excel?
Excel guesses types from the text it sees, and it guesses badly. It turns a product code like 1-2 into a date, drops leading zeros from ZIP codes, and reads $1,299.00 as text because of the symbol and comma. Extract to typed fields so the value is already a number, write the raw number without formatting, and let the spreadsheet handle display.
Is it legal to scrape a website into a spreadsheet?
Collecting publicly available web data is broadly lawful in the United States, and courts have generally declined to treat access to public pages as unauthorized access under the Computer Fraud and Abuse Act. The limits that still apply are the site's Terms of Service, its robots.txt, copyright in the content, and privacy law once the rows contain personal information. This is general information, not legal advice.
What is the difference between scraping to CSV and scraping to JSON?
CSV is flat and JSON is not. If every item has the same simple fields, CSV is the friendlier artifact because anyone can open it. The moment an item has a list of tags, a nested address or an optional block, CSV forces you to flatten or drop it. Scrape to JSON when the data is the input to more code, and to CSV when the data is the answer for a person.
Good questions
Questions about Website to CSV
Explore more
More ways to turn the web into data with ClawEngine
Stop wrangling raw HTML. Get LLM-ready data.
Point ClawEngine at a public page and one call crawls, renders the JavaScript and extracts clean markdown or typed JSON, ready for your RAG pipeline or AI agent. Public, permitted data only.
Crawl · render JS · extract markdown & JSON · robots.txt respected, public data only