Zenrows
Talk to sales Start free

JSON, JSONL, CSV or XML: which output format?

The format you write scraped data in decides how easy it is to resume a failed run, how much memory a downstream job needs, and whether you can keep nested fields. It is a small decision with a long tail.

JSON JSONL CSV XML
Nested data Yes Yes No Yes
Streamable No Yes Yes Awkward
Append safely No Yes Yes No
Human readable Yes Yes Yes Less so
Spreadsheet ready No No Yes No
Typical use APIs, config Large scrape output Flat exports, analysis Feeds, sitemaps

JSONL is the default for a scrape

JSONL, sometimes called NDJSON, is one JSON object per line. That single property changes the operational picture more than it looks.

You can append. A JSON array has to be closed with ], so writing records into one as you go means either holding everything in memory until the end or rewriting the file. With JSONL you append a line per record and stop whenever you like.

A crash keeps its data. Kill a job writing a JSON array and the file is invalid, and you have nothing. Kill one writing JSONL and every completed line is still readable. On a run of a million pages this is the difference between resuming and restarting.

It streams. Downstream jobs read a line at a time with constant memory, rather than parsing a multi-gigabyte array in one go.

It splits trivially. split -l gives you shards for parallel processing.

For a scraping run of any size, this is usually the right choice.

Where the others belong

JSON suits a single response or a small complete result set, and is the natural shape for an API to return. It is a poor fit for an append-only log of scraped records.

CSV is right when data is genuinely flat and a person will open it. Its weakness is nesting: a product with a list of variants has to be flattened or serialised into a cell, and both are lossy in practice. Quoting and encoding cause more real-world breakage than they should.

XML is rarely chosen for new work but often encountered: RSS feeds, sitemaps, and older enterprise interfaces. Worth being able to read even if you never write it.

The practical arrangement

Most pipelines end up with two stages. Write JSONL during collection, because it is append-safe and resumable. Convert to CSV or a database at the end for whoever consumes it. Trying to write the final format during collection is what makes a failed run expensive.

Where Zenrows fits

Extract returns structured JSON per request, which fits either arrangement: write one line per response and you have JSONL. Batch runs a URL list as a managed job and collects results when it finishes, which removes the partial-write problem from your side entirely.

In the docs

Last updated: Aug 16, 2026

Get reliable web data in minutes.

Free plan, 5,000 credits every month, no credit card required.