I Was Drowning in AI Token Limits. Then I Found a Hack That Compresses Text Into Images.
How one developer's frustration with Claude's token costs led to discovering pxpipe - a tool that packs 18 million characters into a 1M token window by converting text to images.
When Your AI Assistant Hits the Token Wall
As a Software Engineer 2 in an era where dependence on AI coding assistants has become the norm, one of the most common issues I've faced is token limitation. You're deep in a debugging session at 2am, Claude Code is your co-pilot, and you're pasting in the fourth consecutive stack trace when you hit it - the context window ceiling.
"I apologise, but I've reached my token limit. Could you start a new conversation?"
It's not just frustrating. It's expensive. Every character of your file contents, every line of terminal output, every historical message in your conversation - they all count against your token budget. And when you're working with dense content like JSON configs, minified code, or database dumps, the numbers spiral quickly.
For context, Claude's text-based encoding runs at roughly 4 characters per token for typical code. That 50KB log file you just pasted? About 12,500 tokens. Do that a few times across a session and you've burned through your daily allocation before lunch.
Text Token
Vision Token
Multiplier
on Real Traffic
The math is simple but brutal. A 1 million token context window - which sounds generous - holds roughly 4 million characters as text. For a large codebase review or a multi-file refactoring session, that's not nearly enough.
Then I stumbled upon pxpipe, and realised someone had found a loophole in the pricing model itself.
The Economics of Vision Tokens
Large language models charge for tokens. But not all tokens cost the same - and not all tokens encode information with the same density.
Text tokens are straightforward. A word, a punctuation mark, a fragment of code. Each consumes one token. Dense content like a JSON object or a minified JavaScript bundle consumes tokens linearly with character count.
Vision tokens, on the other hand, work differently. When you send Claude an image, the token cost is determined by the image's pixel dimensions, not by how much text is rendered inside it. A 1568×728 PNG costs the same number of tokens whether it's a photo of a cat or a densely-packed monospace rendering of 12,000 characters of code.
This creates an arbitrage opportunity. If you can render text as an image using a sufficiently dense monospace font, you can pack far more information into the same token budget.
"An image's token cost is fixed by its pixel dimensions, not by how much text is inside it. That's the entire exploit."
The developer behind pxpipe measured this on real Claude Code traffic and found the compression ratio was approximately 18.3 characters per vision token compared to 4 characters per text token. That's a 4.6× multiplier on effective context window capacity.
Suddenly, that 1 million token window doesn't hold 4 million characters. It holds 18 million.
What Actually Is pxpipe?
pxpipe is a local proxy that sits between your AI client (like Claude Code) and Anthropic's API. It intercepts outgoing requests, identifies large text blocks that would benefit from compression, renders them as dense monospace PNG images, and rewrites the request payload to send images instead of text.
From Claude's perspective, nothing changes. It receives the content, processes it using its vision capabilities, and responds normally. From your perspective, your token consumption drops by 60-70% on typical workloads - and your effective context window expands massively.
How It Works
The architecture is conceptually clean:
127.0.0.1:47821
When you start the proxy and point your Claude Code instance at it, pxpipe intercepts every /v1/messages request. It scans the request body for three types of content blocks:
- Large tool results - file contents, command output, log dumps over approximately 6,000 characters.
- Older conversation history - messages from earlier in the session that are still in context but no longer frequently referenced.
- Static system prompts - large instruction blocks and tool documentation that don't change between requests.
For each candidate block, pxpipe runs a profitability calculation. It counts the current text token cost using Anthropic's token counting API, estimates the vision token cost for the rendered image at a given pixel density, and only applies the transformation if the savings exceed a threshold (accounting for the slight quality loss inherent in vision encoding).
If compression is profitable, the text is rendered to a PNG using a monospace font optimised for readability at small sizes. The default profile for Claude Fable 5 uses 5×8 Spleen font at 1568×728 resolution, packing roughly 12,000 characters per page.
The transformed request - now containing image blocks instead of text blocks - is forwarded to Anthropic's API. Claude processes it normally, and the response streams back through the proxy unmodified.
# Install and run the proxy npx pxpipe-proxy # Point Claude Code at the proxy ANTHROPIC_BASE_URL=http://127.0.0.1:47821 claude # Dashboard available at: # http://127.0.0.1:47821/
It's Lossy, and That Matters
This is not a lossless compression scheme. You're trading token cost for fidelity, and you need to understand exactly what you're losing.
When Claude processes an image of text, it's not performing OCR in the traditional sense. It's using its vision encoder - a neural network trained to extract semantic meaning from pixels. For most natural language and well-formatted code, this works remarkably well. The model reads the text, understands it, and reasons about it as if it were sent as text tokens.
But vision encoding is probabilistic. When a glyph is ambiguous - a zero vs. the letter O, a lowercase L vs. the number 1 - the model uses linguistic context to disambiguate. Most of the time, it gets it right. But for byte-exact values like cryptographic hashes, API keys, database IDs, or random strings with no linguistic structure, it can fail silently.
The pxpipe repository includes benchmark data. When asked to recall exact 12-character hexadecimal strings embedded in compressed image pages:
Claude Fable 5: 13 out of 15 recalled perfectly (86.7% accuracy)
Claude Opus 4.8: 0 out of 15 recalled perfectly (0% accuracy - which is why Opus is opt-in only via explicit configuration)
For this reason, the documentation is explicit: byte-exact values must stay as text. Anything where a single character error would break functionality - credentials, hashes, database primary keys - should not be compressed.
In practice, this means you need to be selective. Compress dense logs, stack traces, documentation, and code where the semantic meaning is what matters. Leave short, exact values as text. The proxy's profitability gate helps here - it won't compress small blocks where the token savings are marginal.
Does It Actually Work in Production?
The repository includes benchmark results from SWE-bench (a standard software engineering task evaluation suite) and custom tests. The numbers are instructive.
SWE-bench Lite (10 Tasks)
Accuracy: 10/10 solved with pxpipe enabled, 10/10 without. Token reduction: 65% on request payloads. The compression did not degrade task-solving capability for these tasks, which involved debugging Python codebases with large file contexts.
SWE-bench Pro (19 Tasks)
Accuracy: 14/19 with pxpipe, 15/19 without. Token reduction: 60%. The one-task regression is within statistical noise for this benchmark, but it demonstrates the real risk - lossy compression can, on occasion, degrade performance when exact string matching is critical.
Novel Arithmetic (Synthetic Test)
Fable 5 was given 100 novel arithmetic problems embedded in compressed image pages. Accuracy: 100/100 at 38% token reduction. This suggests that for well-structured, semantically rich content, the vision encoder is highly reliable.
Gist Recall A/B Test
Two groups of 98 document summaries were tested - one sent as text, one as compressed images. Recall accuracy: 98/98 on both arms. For natural language content, the compression is effectively transparent.
The Actual Cost Savings
Let's make this concrete with real pricing from Anthropic's published rate card (as of July 2026, Fable 5 list price).
Text input tokens: $3 per million tokens
Vision input tokens: Varies by image resolution, approximately $4.50 per million tokens at typical densities
Wait - vision tokens cost more per token. How does this save money?
Because you're sending far fewer tokens. The 18.3 chars/token compression ratio means that even though vision tokens are 1.5× more expensive per token, you're using 4.6× fewer tokens overall.
Text Tokens
Vision Tokens
Reduction
Savings
For a 50,000 character file (typical for a large source file or config):
As text: ~12,500 tokens at $3/M = $0.0375
As compressed image: ~2,730 vision tokens at $4.50/M = $0.0123
Savings per file: $0.0252 (67% reduction)
Multiply that across hundreds of files in a codebase review session, and the savings compound quickly. For teams running AI-assisted development at scale - particularly with tools like Claude Code that operate over entire repositories - the reduction in API costs can be substantial.
When Should You Actually Use This?
pxpipe is not a universal solution. It's a workload-specific optimisation that wins on certain content profiles and loses on others. Here's the decision matrix:
Use pxpipe when:
- Your content is dense. Log files, minified code, JSON dumps, database exports, stack traces. The denser the text, the better the compression ratio.
- You're hitting context limits. If token exhaustion is blocking your workflow, the 4.6× context expansion is transformative.
- Semantic understanding is sufficient. If the AI needs to reason about the content's meaning rather than reproduce it byte-perfectly, compression is safe.
- You're using Fable 5 or Sol. These models have strong vision encoders optimised for text-in-images. The measured accuracy is high enough for production use.
Don't use pxpipe when:
- Byte-exact recall is required. Cryptographic operations, credential handling, hash verification - anything where a single character error breaks functionality.
- Your content is sparse prose. Natural language with typical formatting doesn't compress well. The proxy will likely skip it via the profitability gate.
- You're using Opus 4.8. The verbatim recall failure rate is too high for general use. Only enable Opus via explicit opt-in if you understand the risks.
- Latency matters more than cost. Rendering text to PNG and encoding images adds overhead. If your workflow is latency-sensitive, the cost savings may not justify the slowdown.
pxpipe defaults to Claude Fable 5 only. Other models (Sol, Opus 4.7/4.8, GPT 5.5, Grok) can be enabled via the PXPIPE_MODELS environment variable, but the failure characteristics vary. Test thoroughly before relying on compression with non-default models.
Running pxpipe in Your Workflow
The barrier to entry is deliberately low. It's a Node.js proxy with zero configuration required for basic use.
# 1. Start the proxy (runs on port 47821 by default) npx pxpipe-proxy # 2. Configure your AI tool to use the proxy export ANTHROPIC_BASE_URL=http://127.0.0.1:47821 # 3. Run Claude Code (or any Anthropic API client) claude
That's it. The proxy is now intercepting your requests, compressing where profitable, and logging every transformation to ~/.pxpipe/events.jsonl for audit purposes.
The Dashboard
Navigate to http://127.0.0.1:47821/ in your browser and you'll see a live dashboard showing:
- Total tokens saved across all requests since the proxy started
- A visualisation of the last compressed page (so you can verify the rendering quality)
- Per-request profitability metrics
- Model-specific compression statistics
The dashboard is particularly useful for tuning. If you notice that certain content types are being compressed but causing failures downstream, you can add exclusion patterns via environment variables.
Library API
If you want tighter integration, pxpipe exposes a JavaScript library for programmatic use:
import { renderTextToImages, transformAnthropicMessages } from "pxpipe-proxy"; // Render text to compressed image pages const { pages } = await renderTextToImages(largeLogFile); // Transform an Anthropic API request payload const { body, applied, info } = await transformAnthropicMessages({ body: requestBytes, model: "claude-fable-5", }); // `applied` is true if compression was profitable // `info` contains token savings breakdown
What This Tool Cannot Do
Be clear-eyed about the constraints. pxpipe is powerful within its niche, but it's not magic.
It's Lossy
This cannot be overstated. The failure modes are silent. The model will not tell you "I couldn't read character 47." It will give you a plausible wrong answer. For any workflow where exact string matching is critical - test assertions, hash verification, credential parsing - keep that content as text.
It's Local-Only
The proxy runs on your machine. If you're using a hosted AI service or a web-based IDE, you can't intercept the requests. This is a tool for developers running Claude Code locally or using the Anthropic API directly from code.
It Doesn't Help Output Tokens
pxpipe only compresses input (requests to the API). Claude's responses still come back as text tokens. If your bottleneck is output token cost (e.g., the model generating large code files), this tool doesn't address it.
Model Coverage Is Limited
The default profile is tuned for Fable 5. Other models require opt-in configuration and have not been as thoroughly tested. The vision encoder quality varies significantly between models - what works reliably on Fable may fail on Opus.
What This Means for AI-Assisted Development
pxpipe is a symptom of a deeper tension in the current AI pricing model. As context windows grow - Claude now offers 1 million tokens, and there are rumours of 10 million token windows in development - the economic pressure to fill those windows efficiently grows with them.
Token-based pricing made sense when context was scarce. But as models become more capable of processing multimodal input, the abstraction starts to crack. A vision token and a text token are not equivalent in information density, yet they're priced as if they were.
pxpipe exploits that gap. It's a clever hack, and for workloads that fit its profile, it's transformative. But it's also a signal that the pricing model will need to evolve. As more developers discover techniques like this, providers will either adjust vision token pricing to close the arbitrage, or they'll move toward pricing based on actual compute and information content rather than token count.
"This tool exists because the pricing model has a seam. The question is whether that seam is a feature or a bug."
For now, if you're a developer hitting token limits regularly - particularly in data-heavy workflows like log analysis, debugging complex distributed systems, or large-scale refactoring - pxpipe is worth evaluating. The setup cost is low, the dashboard gives you immediate feedback, and the token savings are measurable.
Just remember: it's lossy. Test it on your actual workload. Verify that the compression doesn't degrade the AI's performance on your specific tasks. And for anything where exact correctness matters, keep it as text.
Repository: github.com/teamchong/pxpipe
Installation: npx pxpipe-proxy
License: MIT (open source, free for commercial use)
Model support: Fable 5 (default), Sol, Opus 4.7/4.8 (opt-in), GPT 5.5, Grok
Credit where credit is due: Massive kudos to the developer behind pxpipe (teamchong on GitHub) for building this remarkably clever tool and open-sourcing it. This article is a deep dive into their work - all the engineering insight belongs to them.
Related essays
- Vite · Frontend Infrastructure
We Blamed Vite For A 90-Second Local Load. The Real Bottleneck Was The 11,516 Modules We Asked It For.
A local Vite page took 90 seconds to load because eager route imports pulled 11,516 modules into one page load. Making routes lazy cut it to 54 modules and 10.54 seconds. The mechanism, how to count your own modules, and where the fix stops working.
- AI Engineering · Video Production
I Gave Claude 500 GB of Raw Footage. It Built a 29-Minute 4K Film.
A practical AI-assisted editing case study for first-time creators and experienced editors: 500 GB of footage, three rebuilds, custom cleanup, 3D maps and a finished 4K film.
- JavaScript · Browser Internals
setTimeout(fn, 0) Is Not Zero. In A Background Tab, Your 100ms Timer Runs Once A Minute.
The delay you pass to setTimeout is a minimum. Measured in Chromium, Firefox, WebKit and Node: the 4ms nesting clamp, hidden tabs throttled to 1 second, Chrome's once-a-minute intensive throttling after 5 minutes, a 30-day timer that fires instantly, and what to use instead.