Integration Yard · Apify tools

Compact, Lossless JSON Output for LLM Agents: How Much Do You Actually Save?

Published October 18, 2026 · Integration Yard

When you hand scraped data to an LLM as an array of JSON objects, every row repeats every key name. For a 400-row export that's thousands of tokens spent on "title", "view_count" and "author_name" over and over before the model ever sees a single value. We measured how much that actually costs, and built a lossless alternative into five of our actors.

The fix: columnar, but still lossless

Instead of an array of objects, send one header listing the columns once, then one array per row:

{"format":"columnar-v1","columns":["id","title","views"],"missing":"¤",
 "rows":[["BV1xx","2026 keyboard roundup",12034],["BV2yy","¤",877]]}

A row that lacks a key gets a reserved marker ("¤" by default, and the encoder picks a different one automatically if that symbol ever collides with real data) instead of being padded with null — so "this field doesn't exist on this row" is never confused with "this field is explicitly null". Decoding is five lines of Python and gets back the exact original rows:

def decode_columnar(payload):
    cols, marker = payload["columns"], payload["missing"]
    return [{c: v for c, v in zip(cols, row) if v != marker}
            for row in payload["rows"]]

Results: 882 real rows, five actors

We exported real rows from five actors that share this China-region scraper codebase and measured GPT-4o's o200k_base tokenizer against pretty-printed JSON (indent=2), minified JSON, and the columnar format above:

ActorRowsvs pretty JSONvs minified JSON
AliExpress Scraper13043.1% smaller25.6% smaller
Bilibili Scraper40641.9% smaller25.9% smaller
Douban Scraper15039.6% smaller22.3% smaller
Weibo Scraper11924.8% smaller4.9% smaller
WeChat Articles Scraper7712.8% smaller6.2% smaller
All five combined882 ~34% smaller~18% smaller

Savings range from 13% to 43% depending on the actor, averaging about 34% across all 882 rows versus pretty JSON. The pattern is consistent: more fields, more rows, and shorter values mean a bigger win, because the repeated key names are a larger share of the payload. WeChat Articles gains the least because each row is mostly unique article text — key names are already a small fraction of the bytes. Weibo gains less than Bilibili/Douban/AliExpress because its rows mix two very different shapes (22-key posts alongside 10-key comments), which forces the "missing" marker into the shorter rows.

Why not a smarter (lossy) compressor?

We also benchmarked an AI-oriented compression library (headroom) on the same files. It reached higher headline compression on paper, but it dropped rows or fields on 7 of the 8 sample datasets we tested it against. That's an acceptable tradeoff for an agent's disposable scratch memory, but not for data a customer is paying us to deliver intact. The columnar format above is the one we shipped because every row we promise you is a row you actually get back, byte for byte, after decoding.

Try it

Set "outputFormat": "compact" on any run of these actors. The run still pushes the same rows to the dataset at the same price — billing is unaffected. The actor additionally writes an OUTPUT_COMPACT key to the run's key-value store with the columnar JSON above, which is cheaper to hand to an LLM than the plain dataset export:

Disclosure: we build and maintain these actors.