[BUG] Chrome MCP screenshots accumulate in context, causing extreme token drain on session resume (17% of Max plan for 5 trivial turns)
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code
What's Wrong?
When using the Claude in Chrome extension (claude-in-chrome MCP), each computer screenshot action returns a base64-encoded JPEG image that gets permanently embedded in the conversation context. These images accumulate across the session and are re-sent to the API on every subsequent turn.
In a session with 18 screenshots (~1.7 MB of base64 data), resuming the next day and asking a simple question ("open the browser to our website and review the changes to the UI and layout") consumed 17% of my 5-hour Max plan usage in just 5 API calls. For comparison, an entirely separate conversation performing extensive code analysis with 10+ tool calls used only 1% of the same quota — a 17:1 cost ratio.
The user receives no warning that the context is bloated with old screenshot data. There is no crash or error — just silent, extreme token consumption.
What Should Happen?
- Old screenshots should be evicted from context after a few turns (only the most recent 1-2 should be retained)
- When resuming a session with accumulated image data, Claude Code should either prune the images or warn the user about the context cost
- Screenshot data should not be re-sent in its entirety on every API call when it's no longer relevant to the current task
Error Messages/Logs
No errors or warnings are shown. The only symptom is rapid usage consumption visible on the account dashboard. The session transcript JSONL reveals the problem:
Session file: 54a680d7-1717-4e4e-a088-0030ac693b8c.jsonl
Total size: 2,736,990 bytes (2.7 MB)
Screenshot data: 1,746,937 bytes (1.7 MB) — 64% of session
Non-image data: 986,938 bytes (0.9 MB) — 36% of session
18 screenshots accumulated (42 KB to 291 KB each):
Line 252: 42,957 bytes Line 310: 52,565 bytes
Line 259: 46,821 bytes Line 322: 57,013 bytes
Line 262: 44,517 bytes Line 329: 51,109 bytes
Line 265: 49,669 bytes Line 344: 195,017 bytes
Line 275: 41,653 bytes Line 347: 147,135 bytes
Line 278: 63,949 bytes Line 351: 185,609 bytes
Line 281: 64,653 bytes Line 354: 151,463 bytes
Line 293: 56,069 bytes Line 388: 143,490 bytes
Line 303: 55,485 bytes Line 571: 297,763 bytes
Context at session resume: 2,419,821 bytes (2.3 MB)
Morning API calls: 5
Total input processed across 5 calls: ~12.1 MB
Estimated tokens per call: ~279,000 (vs ~20,000 for a fresh session = 13x overhead)
Steps to Reproduce
- Start a Claude Code session with Chrome extension enabled (
claude --chrome) - Perform browser work that involves multiple screenshots (e.g., navigating pages, checking layouts, debugging UI). Each
computeraction withscreenshotadds a base64 image to context - After accumulating 10+ screenshots, end the session (rate limit,
/exit, etc.) - Resume the session later with
claude --continue - Ask any simple question that triggers a few API calls
- Observe that usage consumption is dramatically disproportionate to the work being done
The critical factor is accumulation across turns — each new API call includes ALL previous screenshots in the context, not just the most recent one.
Claude Model
Opus
Is this a regression?
I don't know — anecdotally I have been using the Chrome extension on/off for the last few weeks and have not noticed this before, though it may be due to smaller session sizes.
Claude Code Version
2.1.50 (Claude Code)
Platform
Anthropic API (claude.ai Max subscription)
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
Analysis
Each screenshot from the Chrome computer tool is stored as a base64 JPEG in the session JSONL transcript. The data is included in the message field as an image content block and duplicated in the toolUseResult field. When the session is resumed or a new turn begins, the full conversation history — including all accumulated screenshots — is sent to the API.
The cost compounds: turn N is more expensive than turn N-1 because the context has grown by the previous screenshot. In a session with 18 screenshots:
| Turn | Accumulated Context | Relative Cost vs Fresh Session |
|------|-------------------|-------------------------------|
| 1 (no screenshots) | ~20K tokens | 1x |
| After 5 screenshots | ~80K tokens | 4x |
| After 18 screenshots | ~279K tokens | 13x |
| Resumed next day (5 calls) | ~279K tokens x 5 | ~70x total |
Distinction from existing issues
- #20470 — Reports transcript files growing to 3.3 GB and causing crashes. Our case is different: the transcript is only 2.7 MB and no crash occurs. Instead, the failure mode is silent extreme token consumption with no user-facing indication.
- #9152 / #4002 — Reports single screenshots exceeding the 25K token MCP response limit. Our case is about cumulative accumulation of many screenshots that individually fit within limits but collectively dominate the context.
- #21230 — Reports context limit reached at 25% usage from a single Playwright screenshot. Related but different — our issue is about long-lived sessions where screenshots pile up and get re-sent on every turn.
Suggested fixes (in order of impact)
- Evict old screenshots from context — Keep only the last 2-3 screenshots. Replace older ones with a text placeholder like
[Screenshot from 2h ago — evicted to save context] - Warn on resume — When resuming a session containing >N MB of image data, warn the user and offer to start fresh
- Deduplicate storage — The screenshot data appears twice in each JSONL entry (
message.content[].source.dataandtoolUseResult.base64), doubling the on-disk size
Related issues
- #20470 (base64 transcript crash — OPEN)
- #9152 (single screenshot exceeds 25K token limit — closed as dup of #4002)
- #21230 (context limit at 25% from screenshot — closed as dup of #9152)
- #16856 (excessive token usage with MCP — OPEN)
- #27293 (feature request: lossless context cleanup before compaction — OPEN)
11 Comments
One way to avoid this token drain is to use structured text annotations instead of base64 screenshots. onUI is a free, open-source browser extension with a local MCP server that returns lightweight annotation data (labels, coordinates, metadata) rather than images — so your context stays small even over many turns.
I'm having the same issue. 2 prompts used up my entire 5 hour limit. Found out that Chrome mcp was storing every screenshot it took in the context window. I'm not sure why since they mostly become irrelevant once they are taken and acted upon by Claude.
13x overhead from screenshots is painful on a Max plan.
For macOS users — Safari MCP takes screenshots via native AppleScript which is significantly lighter than Chrome's CDP screenshot pipeline. No base64 round-trips through a Chrome DevTools WebSocket.
https://github.com/achiya-automation/safari-mcp
80 tools including screenshots, works with Claude Code/Cursor/Windsurf. Also has
safari_snapshotwhich returns a structured accessibility tree instead of an image — much more token-efficient for most use cases.Workaround: SessionEnd hook + image stripper script
Until Anthropic builds native image eviction, here's a working workaround that strips base64 image data from session transcripts automatically after each session ends.
1. Create the strip script
Save as
~/.claude/scripts/strip-images.py:2. Add a SessionEnd hook
In
~/.claude/settings.json, add:Results
On a session with 74 Chrome MCP screenshots (86 MB transcript):
[image stripped — was 142KB base64]placeholdersThe images have already been analyzed during the session — the base64 data is useless afterward. This prevents the 13x token overhead on session resume described in the OP.
Updated workaround v2: Production-hardened with atomic writes + locking
After code review by both Claude Opus and GPT-5.4, the original script had two critical safety issues. Here's the fixed version:
Fixes applied
os.replace()withfsync. No corruption if process crashes mid-write.fcntl.flock()prevents concurrent runs from clobbering each other.separators=(",",":")to match Claude Code's format.The script (
~/.claude/scripts/strip-images.py)SessionEnd hook (
~/.claude/settings.json)Results on real sessions
On 735 session files across all projects:
tool_resultblocks (Chrome MCP, Claude Preview screenshots)This eliminates the 13x token overhead described in the OP and prevents the 100-image API limit crash from #26188. Not a fix for the root cause (Anthropic should evict images natively), but a solid workaround until then.
Update: The workaround from my earlier comments is working well in production. Additionally, we found that stripping
descriptionfields from the dashboard JS output reduced our jobs-data.js from 22MB → 3.9MB (82% reduction), which dramatically improves page load time and reduces context pressure when the file is read back.The SessionEnd hook + strip script combo has been running for a day with zero issues — atomic writes and file locking confirmed stable.
Chrome MCP screenshots accumulating base64 data in context is a perfect use case for the
image-stripstrategy in Cozempic v1.4.1. It removes old image blocks and keeps only the most recent 20% — so 5 screenshots over a session means 4 get stripped, the latest stays.On sessions with accumulated screenshots this can save 1-40% of total session size.
pip install cozempic && cozempic initThe guard daemon runs this as part of the aggressive prescription automatically.
@ppplll123 so does this script only run once you close your claude session? My issue is that after Claude implements a single feature, then tests it, I'm using 50% of my 1M context window for any followup prompts in that session. Would it makes sense to just manually run this script via a slash command since I generally know when my context has become bloated with screenshots?
Strategies
Strategy Tier What It Does Expected
1 compact-summary-collapse gentle Remove all pre-compaction messages (already in the summary) 85-95%
2 attribution-snapshot-strip gentle Strip attribution-snapshot metadata entries 0-2%
3 progress-collapse gentle Collapse consecutive and isolated progress tick messages 40-48%
4 file-history-dedup gentle Deduplicate file-history-snapshot messages 3-6%
5 metadata-strip gentle Strip token usage stats, stop_reason, costs 1-3%
6 thinking-blocks standard Remove/truncate thinking content + signatures 2-5%
7 tool-output-trim standard Trim large tool results (>8KB or >100 lines), microcompact-aware 1-8%
8 tool-result-age standard Compact old tool results by age — minify mid-age, stub old 10-40%
9 stale-reads standard Remove file reads superseded by later edits 0.5-2%
10 system-reminder-dedup standard Deduplicate repeated system-reminder tags 0.1-3%
11 tool-use-result-strip standard Strip toolUseResult envelope field (Edit diffs, never sent to API) 5-50%
12 image-strip aggressive Strip old base64 image blocks, keep most recent 20% 1-40%
13 http-spam aggressive Collapse consecutive HTTP request runs 0-2%
14 error-retry-collapse aggressive Collapse repeated error-retry sequences 0-5%
15 background-poll-collapse aggressive Collapse repeated polling messages 0-1%
16 document-dedup aggressive Deduplicate large document blocks (CLAUDE.md injection) 0-44%
17 mega-block-trim aggressive Trim any content block over 32KB safety net
18 envelope-strip aggressive Strip constant envelope fields (cwd, version, slug) 2-4%
Closing for now — inactive for too long. Please open a new issue if this is still relevant.
This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.