> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bloklake.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Arrow vs JSON

> Two response formats for the same rows. Which one to use, and what each costs.

The same request body works on two endpoints:

| | `POST /query` | `POST /query/json` |
| - | - | - |
| Body | Apache Arrow IPC streams, one per row type | one JSON object |
| Binary values | raw bytes | `0x` hex strings |
| Large integers | 16/32-byte big-endian binary | decimal strings |
| Size for the same rows | 1× | **about 2–2.5×** |
| Billed on | the Arrow row data | the JSON row data |
| Page size | 100,000 objects / \~8 MB | 100,000 rows |
| Streaming | yes: the first rows arrive while the server is still reading | no: built in full, then sent |
| Best for | backfills, pipelines, dataframes, anything repeated | `curl`, exploring, debugging, tiny scripts |

## Measured sizes

The same rows, from real responses:

| Query | Rows | Arrow | JSON | JSON / Arrow |
| - | - | - | - | - |
| Ethereum ERC-20 transfers, 100 blocks, 7 fields | 16,190 | 2.66 MB | 6.72 MB | 2.53× |
| Robinhood Chain ERC-20 transfers, 100 blocks, 7 fields | 2,831 | 0.47 MB | 1.18 MB | 2.51× |
| Ethereum transactions, 10 blocks, 7 fields | 1,996 | 2.28 MB | 4.66 MB | 2.04× |

The fields are those of [Estimating costs](https://docs.bloklake.com/billing/estimating-costs.md#measured-examples).
JSON doubles every binary byte (hex) and adds the column names to every row. Because you're
[billed by the bytes you receive](https://docs.bloklake.com/billing/how-billing-works.md), **the same data costs 2–2.5× more
as JSON.**

## Use Arrow when

* You're reading more than a few thousand rows, or running the same query repeatedly.
* The data goes into a dataframe, a database or a file: pandas, Polars, DuckDB, Spark,
  ClickHouse and BigQuery all read Arrow without conversion.
* You want typed columns: `UInt64` block numbers, fixed-size binary hashes and addresses,
  nested lists of structs.

## Use JSON when

* You're exploring with `curl` and `jq`.
* You're debugging a filter and want to read the rows.
* The script is tiny, and adding an Arrow library isn't worth it.

> [!TIP]
>
> A common workflow: build and check a query with `/query/json` on a small range, then change the
> path to `/query` for the real run. The request body is identical.

## What's the same

* The request body, the filters, the fields and the validation.
* Which rows come back and in what order.
* Pagination: both return `next_block` and stop at the same kinds of limits.
* The metadata values (`archive_height`, `finalized_block`, `next_block`, …). Arrow puts them
  in the schema metadata as `bl.*` strings; JSON puts them in the body as numbers. See
  [Response metadata](https://docs.bloklake.com/responses/metadata.md).

Next: [Reading Arrow](https://docs.bloklake.com/responses/reading-arrow.md) or [The JSON format](https://docs.bloklake.com/responses/json.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.