Back to blog

Saturday, July 4, 2026

pxpipe Packs Prompts Into PNGs to Slash Token Costs by 70% — Yes, It Actually Works

cover

Here's a sentence I didn't expect to write in 2026: the most cost-effective way to send 48,000 characters of system prompt to Claude Fable 5 is to render it as a PNG file.

pxpipe is a new open-source tool from developer Steven Chong that converts long text inputs into compact PNG images before sending them to Anthropic's API. It sounds like a bizarre hack because it is one. It also happens to cut end-to-end token costs by 59 to 70 percent on real Claude Code and Fable 5 workloads, with no code changes and minimal accuracy loss on supported models.

This thing shipped on July 3 and is already version 0.7.1. I'd bet on fast iteration — the repo itself was mostly written by AI agent sessions running behind pxpipe, reading their own collapsed history as image pages while they worked. (More on that dogfooding in a moment.)

How the Trick Works

The exploit is rooted in a pricing asymmetry that's existed since Anthropic introduced image support:

  • Text costs roughly 1 token per character on average.
  • Images cost a fixed number of tokens based on their pixel dimensions, regardless of how much text is embedded in them.

A 1928×1928 PNG costs about 4,761 vision tokens. That same image can hold approximately 92,000 densely packed characters. That works out to 3.1 characters per image-token vs. roughly 1 character per text-token on typical Claude Code traffic. The breakeven point is around 19 characters per token — anything denser than that, and you're leaving money on the table by sending it as text.

pxpipe is a local proxy that sits on 127.0.0.1:47821 and intercepts /v1/messages requests to Anthropic (and OpenAI). It applies a per-request profitability gate: if the compression ratio is favorable, it renders the static, bulk parts of the input — system prompts, tool documentation, older chat history — as PNG pages. Recent messages and model responses pass through as text. The result is transparent to the client: Claude Code, Cursor, or any tool pointed at the proxy just sees a cheaper response.

The dashboard at http://127.0.0.1:47821/ shows live token savings, side-by-side conversion views, model allowlist chips, and a kill switch. It's well-designed for a v0.7.

The Numbers That Matter

Chong publishes transparent, reproducible measurements. Every request gets a count_tokens probe on the original uncompressed body (counterfactual) sent in parallel with the real forward. Cache pricing is applied identically to both sides to prevent double-counting. The formula is documented in src/core/baseline.ts. Here's what the data shows:

MetricValue
End-to-end bill reduction (13,709 requests)59%
Compressed-portion reduction (8,904 requests)~70%
Demo session: plain$42.21
Demo session: pxpipe$6.06
SWE-bench Lite request size reduction−65%
SWE-bench Lite task resolution10/10 both arms

The SWE-bench Lite result is worth highlighting: identical task resolution with a two-thirds reduction in request size. On SWE-bench Pro, the results were 14/19 with pxpipe vs. 15/19 without — the single-task delta was run-to-run variance, not compression degradation.

Accuracy: Where It Works and Where It Breaks

Chong's FINDINGS.md is refreshingly honest. This is not a lossless compressor. The question is whether the loss matters for your use case.

Fable 5 (Default — On by Default)

TestNAccuracyToken Savings
Novel arithmetic (fresh random numbers)100100%−38%
Gist recall A/B98/arm98/98
State tracking (value mutated 3×)1818/18
Confabulation guard (lower is better)160/16 (same as text)
Verbatim 12-char hex recall1513/15

Fable 5 reads rendered images with near-perfect accuracy on semantic tasks. The hex recall failure (2/15) is the most instructive: single-glyph confabulations like 125f9e6e1c77125f9e6a1c77 (e→a). The model doesn't know it misread it. This is a silent confabulation — worse than an error, because there's no error signal.

Opus 4.8 (Opt-in — Off by Default)

Opus is explicitly opt-in for good reason. Verbatim hex recall: 0/15. The model either returns empty or confidently incorrect values. Novel arithmetic accuracy drops to 93%. Opus 4.7 and 4.8 are off by default, and pxpipe says so in the README instead of fabricating a number. I respect this approach.

What This Means in Practice

  • Agentic coding sessions: pxpipe works great. Agents re-read files before editing them, so even if a hex hash in conversation history gets garbled, the agent checks the actual file system before making changes. The code safety net is real.
  • Pure chat recall: Riskier. Chong reports one real-world failure where a model recalled a person's name from imaged chat history and got it confidently wrong. There's no safety net here.
  • Exact strings in imaged content: Not byte-safe. SHAs, UUIDs, secret keys, and numeric IDs should stay in the text portion. The guardrail for this isn't built yet (acknowledged on the roadmap).

What Gets Compressed vs. What Doesn't

Gets CompressedStays as Text
Large tool_result bodies (file reads, logs, JSON)User messages
Older collapsed chat historyRecent turns
Static system prompt + tool docs slabModel output
(Only when profitability gate says yes)Sparse prose, small blocks
Out-of-scope models

The profitability gate is important: pxpipe doesn't image everything blindly. Sparse prose (novel text, short messages) passes through unchanged because the compression ratio doesn't justify the vision overhead. On my typical Claude Code traffic, that means about 60-70% of requests get imaged and the rest pass through byte-identical.

Setup and Usage

Setup takes about 30 seconds:

# Install
npm install -g pxpipe   # or clone from github.com/teamchong/pxpipe

# Run (proxy on 127.0.0.1:47821)
pxpipe

# Point Claude Code at it
claude code --proxy http://127.0.0.1:47821

# Or set env for any Anthropic client
ANTHROPIC_BASE_URL=http://127.0.0.1:47821

Configuration is minimal. The main knobs are PXPIPE_MODELS (default: claude-fable-5,gpt-5.6) and the dashboard for live toggling. The CLAUDE_CODE_SUBAGENT_MODEL env var lets you route subagents through text-only models for safety.

There's also a library API if you want to integrate pxpipe's rendering directly into your own tooling:

import { renderTextToPngs, transformAnthropicMessages } from "pxpipe";
const imgs = await renderTextToPngs(toolResultText);

The Dogfooding Meta

The README addresses the elephant in the room: "Why does the README read like an AI wrote it? Because one did. Most of this repo's commits — the code and the docs — were authored by Opus/Fable agent sessions running behind pxpipe itself, reading their own collapsed history as image pages while they worked."

The repo itself is an existence proof. If the technique were lossy enough to break coding sessions, the code wouldn't exist.

When to Use pxpipe (and When Not To)

Use it when:

  • You're running long Claude Code sessions with heavy tool-calling loops
  • Your system prompts are large and stable (tool documentation, framework configs)
  • You're working on Fable 5 or GPT 5.6
  • You want transparent cost measurement with per-request counterfactuals
  • You can tolerate single-glyph confabulation risk on non-critical strings

Don't use it when:

  • Byte-exact recall from history is critical (hex IDs, secrets, cryptographic hashes)
  • You're on Opus 4.7/4.8 — the accuracy drop is real and explicit
  • Your workload is mostly sparse prose (the profitability gate handles this, but you'll see less savings)
  • You need the lowest possible latency — PNG encoding adds overhead before requests leave

What This Means for the Ecosystem

pxpipe is important not because it's the ultimate solution to token costs — Anthropic could change image pricing at any time, and if this trick catches on, they probably will. It's important because it reveals something about the pricing models underneath our tooling: image pricing is a feature, not a bug.

Anthropic charges by pixel, not by content, because image processing genuinely uses vision encoder compute proportional to resolution. The token cost reflects the compute cost, not the information density. pxpipe exploits the delta between those two things. It's entirely within the rules — every pixel is real, every image is rendered at native resolution.

The more interesting question is whether this accelerates a trend I'm starting to see: tooling that treats the LLM API pricing surface as something to be optimized around rather than accepted. We've had prompt caching, context window management, and model routing. pxpipe adds image-based compression as another lever. The next iteration is probably a smarter version that sends exact strings as small text payloads alongside the images, getting the best of both worlds.

For now, pxpipe is a practical, well-documented, measurable cost hack for anyone running heavy Claude Code or Fable 5 workloads. The savings are real, the tradeoffs are clearly documented, and it costs nothing to try. Point your local proxy at it for a session and watch the dashboard numbers — you'll either save money or learn something about where your token budget is going.

pxpipe on GitHub | FINDINGS.md — Benchmarks and tradeoffs | The Decoder coverage