Skip to main content
Glama

tokenzip

bytes per image

Vision models count image tokens by tiles, not megapixels. A 3000×2000 screenshot costs Claude exactly the same 1568 tokens whether you upload 6 megapixels or the 1328×885 it internally resizes to. tokenzip computes that exact size per provider and re-encodes the image: same tokens, same detail the model ever sees, far fewer bytes uploaded.

$ tokenzip screenshot.png --provider anthropic

screenshot.png — 3000×2000 (Claude (Anthropic))
  billed tokens : 1568 ≈ $0.0047/image
  model sees    : 1328×885
  pixels to send: 19.6% (80% fewer bytes)
  note          : send 1328×885: identical tokens & detail, 80% fewer bytes

Install / run

npm install @asynx6/tokenzip          # CLI: npx tokenzip, lib: require('@asynx6/tokenzip')
npm install -g @asynx6/tokenzip       # global `tokenzip` command
# or no install at all (zero deps): clone + `node tokenzip.js ...`

Related MCP server: Image Parse MCP

Hook it into your AI tools

Claude Code — never burn 1568 tokens on a bloated Read again. The hook intercepts image Reads, rewrites oversized files into a tokenzip cache, and Claude sees the resized copy:

claude --settings '{"hooks":{"PreToolUse":[{"matcher":"Read","hooks":[{"type":"command","command":"npx -y @asynx6/tokenzip hook claude-code"}]}]}}'

Or add the same block permanently to .claude/settings.json. PNG and baseline JPEG inputs only; anything weird passes through untouched.

Claude Desktop / OpenCode / Cursor / anything that speaks MCP:

{ "mcpServers": { "tokenzip": { "command": "npx", "args": ["-y", "@asynx6/tokenzip", "mcp"] } } }

OpenCode uses the same JSON under mcp in its config (type: "local"). Tools exposed: tokenzip_estimate, tokenzip_optimize (writes a file and tells you exact token/byte deltas), tokenzip_batch_dir.

As a library:

import { PROVIDERS, anthropicTokens } from '@asynx6/tokenzip';
import { optimize } from '@asynx6/tokenzip/optimize';

anthropicTokens(3000, 2000);              // 1568 — what one shot costs
const plan = optimize('anthropic', 3000, 2000);
// plan.best = { w: 1328, h: 885, tokens: 1568 }  — resize to this, bill unchanged

CLI, hook, MCP, and library share the same tested formulas — no drift between "what the tool says" and "what your code does".

What it does

  • Per-provider token math for Claude, GPT-4o+, and Gemini — the resize + tile formulas from each provider's own docs, pinned with tests (512²→255 tokens, 768²→787, 2×768→258, etc.). Formula sources and dates are recorded in FORMULAS.md.

  • Exact mode: shrink to the size the provider's own pipeline ends up at. Token bill unchanged, upload bytes slashed (matters for latency, egress fees, mobile, batch agents that resend images every turn).

  • Budget mode (--max-tokens 300): binary-searches the largest resize that fits your cap, and tells you how many tokens it saves per image.

  • Re-encode (--out): writes the optimized image. PNG (built-in zero-dep encoder, 8-bit) and JPEG (baseline DCT encode; decode accepts baseline JPEG input) — no external binaries.

  • Folder mode (--dir ./shots): per-image analysis across a directory.

Why this saves anything

The money saving is a myth worth killing honestly: tiles are billed on the provider's post-resize dimensions, so resizing first costs you zero tokens saved on a single image. What you actually save:

  1. Upload bandwidth and time — a screenshot batch of 500 images at 80% fewer bytes is a real bill on egress-priced storage and a real wall-clock cut for agents.

  2. Budget mode is where money moves: an agent that sends 1105-token tiles per screenshot but only needs layout understanding can cap at 300 and cut its vision bill ~70%, with the tool finding the sharpest image that fits.

  3. Knowing the floor: images under ~768px are one tile on every provider — making screenshots small is the optimization, and tokenzip shows the exact per-provider breakpoints.

Benchmarks

node bench.mjs regenerates this table in-memory (reproducible, no network, no fixtures):

input (JPEG q85)

size

Anthropic tok

exact→ bytes

budget 300 tok→

screenshot-like

3000×2000

1568

1328×885 · 436 KB → 181 KB (−58%)

512×341 · 34 KB (−805 tok)

chat UI

1280×800

1366

already optimal · 19 KB → 19 KB

512×320 (−1105 tok)

phone shot

1080×2400

1568

727×1616 · 306 KB → 243 KB (−21%)

230×512 (−1190 tok)

The chat-UI row is the honest counter-example: an image already near the provider floor gains nothing — and tokenzip tells you that instead of shrinking something pointlessly.

Limitations (read before trusting)

  • JPEG: baseline encode/decode (4:4:4 + 4:2:0, quality knob). Progressive and lossless JPEG inputs throw a clear error instead of guessing. WebP has no codec in v0.x — convert or help us build it.

  • 8-bit PNGs, non-interlaced.

  • Token formulas match provider docs as of 2026-09; they have changed before. FORMULAS.md pins sources, dates, and the update procedure; test-tokens.js fails loudly when docs and code diverge.

  • Cost figures are order-of-magnitude list-price estimates. Your rate plan differs.

  • Budget mode optimizes pixels-per-token, not task quality. Only you know whether 300 tokens still reads your chart. Check the resized output.

Tests

node test-tokens.js   # 12 provider-math cases against documented examples
node test-png.js      # codec roundtrips, palette, resize, optimize invariants
node test-jpeg.js     # JPEG encode→decode roundtrip vs own decoder + System.Drawing check
node bench.mjs        # regenerates the README benchmark table

Contributing

Start with CONTRIBUTING.md — it explains the codec architecture in one page.

License

MIT

Related MCP Connectors

Related MCP Servers