Screenshots Waste Claude Code Tokens: Fix It

GuidesAugust 20, 20268 min readBy PinVari
Screenshots Waste Claude Code Tokens: Fix It

Screenshots waste Claude Code tokens because every image you paste is re-encoded into roughly 1,300 or more vision tokens, and it is charged again on every turn that image stays in context. The fix is to stop shipping pixels the agent has to decode and instead send the one thing it needs: the resolved, named UI element you are pointing at, as a few dozen tokens of text.

Most advice here stops at "use fewer screenshots," which misses the point. The count is not the problem — a picture is just the most expensive possible way to say "this button."

How many tokens does a screenshot cost in Claude Code?

Anthropic documents the approximation itself: an image costs about (width px × height px) / 750 tokens. Images are also resized so the long edge stays under ~1,568 px and the total under ~1.15 megapixels.

Run the math on that ceiling and a full-window Mac screenshot lands near 1,300 to 1,500 tokens once it is downscaled to fit.

That is one image, once. A UI-feedback loop is never one image.

Key

The token cost of a screenshot is not paid once. Claude Code re-sends the visible conversation on every turn, so an image you pasted five turns ago is still billed at full vision-token price until it scrolls out of the window.

Why do screenshots waste Claude Code tokens every turn?

Language models are stateless. The client re-submits the running transcript on each request, and any image in that transcript is re-tokenized every time. That is why screenshots waste tokens in Claude Code the way they do: the cost compounds instead of clearing.

Do the arithmetic. Three screenshots at ~1,400 tokens each, each lingering five turns before it scrolls off, is over 20,000 tokens — spent on pictures, before a single line of code is discussed.

Text has the same re-billing property, but text is cheap. A pasted stack trace might be 200 tokens; a screenshot of the same stack trace is 1,300-plus and carries less machine-readable signal. Pixels are a lossy, expensive encoding of text the OS already stores as structured data.

What should you send instead of a screenshot?

Send the answer to the question the screenshot was trying to answer: which element, and what about it.

On macOS, the OS already knows. The Accessibility API returns the UI element under any point — its role, its title or value, its frame, its parent chain — through calls like AXUIElementCopyElementAtPosition. That is a naming system for the interface, not a rendering of it.

A resolved element reads like this:

AXButton "Save changes"  ·  window "Project Settings"  ·  {x:840,y:612,w:120,h:36}

That is under 30 tokens, and it is unambiguous in a way a picture never is. The agent does not have to guess which of four similar buttons you meant; it has the label. For the deeper argument on why that removes a whole class of failures, see how AI agents know which UI element you mean.

Tip

When your agent keeps editing the wrong component, the cause is usually the same as the token waste: it was handed pixels and asked to infer intent. Give it the name and both problems disappear at once.

AX tree vs screenshot: which uses fewer tokens?

Here is the same feedback — "the Save button on the settings window is misaligned" — expressed three ways, with realistic token payloads.

What you sendPayloadApprox tokensHow exact is the target?
Full-window screenshotDownscaled PNG1,300–1,500Agent infers from pixels; ambiguous if elements repeat
Screenshot + typed noteImage + ~40 words1,350–1,550Slightly better, still a guess on "which one"
Resolved named element + window textText only60–400Exact: role, label, frame, provenance

The text-only row is not just cheaper. It is more precise, because a name beats a guess. That is the part the "just take fewer screenshots" crowd never says: the cheaper representation is also the more accurate one.

The counterpoint is fair. A screenshot carries visual context a label does not — color, spacing, overlap — and that matters for genuinely visual bugs. We get to when you still need the frame below.

How does PinVari cut the token cost of pointing at UI?

PinVari is a native macOS point-and-speak app. You hold ⌥⌘A, circle or point at any on-screen element, and say what you want. Instead of pasting an image, your agent receives the resolved target.

Concretely, over a local MCP server on 127.0.0.1, the agent gets:

  • the named accessibility element you circled — role, label, frame
  • a confidence score, so a shaky resolve asks instead of silently guessing
  • circled-vs-dwelled provenance, so "you deliberately drew around this" outranks "the cursor passed over that"
  • the window's relevant text, and the browser's real URL read from the AX web area
  • your spoken instruction, transcribed on-device

None of that is a 1,300-token image. It is structured text sized to the task, so the payload scales with the instruction, not your monitor's resolution.

Getting there takes real engineering, because a naive hit-test would resolve to PinVari's own overlay sitting on top. It walks the on-screen window list to hit-test the real app underneath (chainExcludingSelf); it wakes Electron and Chromium apps that build their accessibility tree lazily by setting AXManualAccessibility and retrying until a labeled element appears; and when your point lands on a bare container, it descends to the deepest labeled child. For the API itself, what the macOS Accessibility API is used for covers the mechanics.

Heads up

Resolution is not always possible. On a <canvas>, a game surface, or some remote-desktop windows, the accessibility tree is empty. PinVari falls back to on-device Vision OCR of just the circled region to name it, rather than dumping a full-resolution screenshot into your context.

Because it is a spatial capture, the point-and-speak workflow also binds deictic words — "move this above that" — to the elements your pointer was over at the instant you said each word, from a timestamped pointer trail. That is context a flat screenshot cannot carry at any token price.

When do you still need the pixels?

Send the image when the bug is the pixels: a rendering glitch, a z-index overlap, a color that is subtly wrong, a font that failed to load. No label describes those; the agent has to see them.

Even then you rarely need the whole screen. PinVari crops the screenshot to the region you circled, so if a picture is warranted, it is a small one, and it rides alongside the named element rather than replacing it.

The rule of thumb is simple. If you can name what is wrong, send the name. If you can only show it, send the smallest crop that shows it.

Tip

A good default: text-first, pixels-on-demand. Point and speak for "rename this," "move this," "this is misaligned to the grid." Reach for a cropped image only when the defect is purely visual. For the full picture of what an agent can and cannot see, read can Claude Code see my screen.

Is this the same as computer-use or screen recording?

No, and the difference is the whole token argument. Computer-use style loops feed the model frame after frame and let it reason over pixels, which is exactly the expensive pattern this post is about.

PinVari runs the resolution on your machine — transcription and OCR use Apple's on-device frameworks, no API keys, nothing uploaded by default. The agent you already pay for receives finished text, not a video feed to interpret. The heavy work happens locally, before a single token is billed. The local MCP server design explains how that stays on 127.0.0.1.

That also means you bring your own agent. Claude Code, Cursor, Codex, and Zed all read the same resolved capture over MCP; PinVari does not run an LLM of its own.

Does sending less improve the output, or just the bill?

Both, and the output gain is the bigger one. A tighter, named payload leaves more of the context window for the code and the conversation, and it removes the ambiguity that sends agents editing the wrong thing.

You save the 1,300 tokens you would have paid to describe a button you could have named in twenty. And you save the retry tokens you would have spent correcting a wrong guess — usually the larger of the two.

PinVari is a one-time $39 for the first 500 licenses (then $59), sold through Polar with no subscription for the core app — see pricing. Set against a month of image-heavy agent loops, the math is not close.

FAQ

How many tokens is a screenshot in Claude Code?

By Anthropic's documented approximation, an image costs about (width × height) / 750 tokens, and images are downscaled to roughly 1.15 megapixels maximum. In practice a full-window Mac screenshot lands near 1,300 to 1,500 tokens after resizing, and it is re-billed every turn it stays in context.

Why does reducing screenshots lower my token usage so much?

Because images are re-sent on every turn, not just once. An image pasted early in a session keeps costing its full vision-token price on each subsequent request until it scrolls out of the window, so one screenshot can be billed many times over a conversation.

What is cheaper than sending a screenshot to an AI coding agent?

Sending the resolved element as text. A named accessibility element — role, label, frame — plus a short slice of window text is typically 60 to 400 tokens, versus 1,300-plus for the image, and it is more precise because the agent has the element's actual name instead of a visual guess.

Does using the AX tree instead of a screenshot lose information?

For UI-targeting tasks, no — it gains information, because you get the exact element name and frame rather than a guess from pixels. You only lose signal for genuinely visual defects like rendering glitches or color errors, where PinVari sends a small cropped image alongside the named element.

Can I stop sending screenshots to Claude Code entirely?

Almost, but not always. Text-first handles rename, move, reorder, and "which element" feedback with no image at all, and you reach for a cropped screenshot only when the bug is purely visual, so images become the exception rather than every turn's default.

Is PinVari's resolution done on-device or in the cloud?

On-device. Transcription and OCR run through Apple's frameworks locally, the resolved capture is served to your agent over a local MCP server on 127.0.0.1, and nothing is uploaded by default — you bring your own agent, and PinVari does the naming before any token is spent.

Hand your agent the exact element

PinVari resolves what you point at into a named, executable instruction — on-device, no keys, your own agent. If you run Claude Code, it is one command.

claude mcp add pinvari
Get PinVari — $39 →