mendableai/firecrawl
120 source files scanned · 38 LLM call site(s) · ~13% of LLM spend looks recoverable (static heuristics)
$13.5per 10k runs today (gemini-2.5-flash, ~2000 prompt tokens)
$11.75per 10k runs with fixes applied

[](https://tokenzero.sh/audit/mendableai/firecrawl)
Models referenced
gemini-2.0-flash ×6gemini-2.5-flash-image-preview ×5gemini-2.5-pro-exp-03-25 ×5claude-3-7-sonnet-20250219 ×4gpt-4.1-mini ×3gpt-5 ×2 (cheaper sibling: gpt-5-mini)claude-3-5-sonnet-20240620 ×1gpt-4o ×1 (cheaper sibling: gpt-4o-mini)gpt-4o-mini ×1
Findings
| Severity | Where | Finding | Est. |
|---|---|---|---|
| high | apps/api/src/scraper/scrapeURL/transformers/llmExtract.ts:860 | gpt-5 used for a task whose prompt reads like extraction/classification Full-size pricing ($1.25/M in, $10/M out) on a constrained task. gpt-5-mini costs ~80% less per call at this shape. Fix: Opt into TokenZero cascade routing (`X-TokenZero-Cascade: auto`) so this call is routed to gpt-5-mini only when the classifier is confident (an opt-in shadow parity monitor is coming; nothing is promised), or switch the model here behind an eval. | 80% |
| medium | examples/gemini-2.5-crawler/gemini-2.5-crawler.py:195 | gemini-2.5-pro used for a task whose prompt reads like extraction/classification Frontier pricing ($1.25/M in, $10/M out) on a constrained task. gemini-2.5-flash costs ~75% less per call at this shape. Fix: Opt into TokenZero cascade routing (`X-TokenZero-Cascade: auto`) so this call is routed to gemini-2.5-flash only when the classifier is confident (an opt-in shadow parity monitor is coming; nothing is promised), or switch the model here behind an eval. | 75% |
| medium | examples/gemini-2.5-crawler/gemini-2.5-crawler.py:313 | gemini-2.5-pro used for a task whose prompt reads like extraction/classification Frontier pricing ($1.25/M in, $10/M out) on a constrained task. gemini-2.5-flash costs ~75% less per call at this shape. Fix: Opt into TokenZero cascade routing (`X-TokenZero-Cascade: auto`) so this call is routed to gemini-2.5-flash only when the classifier is confident (an opt-in shadow parity monitor is coming; nothing is promised), or switch the model here behind an eval. | 75% |
| medium | examples/gemini-2.5-web-extractor/gemini-2.5-web-extractor.py:59 | gemini-2.5-pro used for a task whose prompt reads like extraction/classification Frontier pricing ($1.25/M in, $10/M out) on a constrained task. gemini-2.5-flash costs ~75% less per call at this shape. Fix: Opt into TokenZero cascade routing (`X-TokenZero-Cascade: auto`) so this call is routed to gemini-2.5-flash only when the classifier is confident (an opt-in shadow parity monitor is coming; nothing is promised), or switch the model here behind an eval. | 75% |
| medium | apps/api/src/lib/deterministicJson/llm/prompts.ts:38 | 4 static prompt template(s), ~2,843 tokens, and no caching directive anywhere in the repo Most call sites use providers with automatic prefix caching, which only pays off when these templates are sent as a byte-identical prefix: static template first, nothing volatile (dates, ids, user data) interpolated into it. Fix: Keep templates first and static; TokenZero adds a stable `prompt_cache_key` so related requests land on the same cache. | 12% |
| medium | apps/api/src/scraper/scrapeURL/transformers/llmExtract.ts:508 | "gpt-4.1-mini" retires on 2027-01-14 The provider announced on 2026-10-14 that this model retires on 2027-01-14 (80 days). Recommended replacement: gpt-6-luna. Fix: Move to gpt-6-luna (eval first); TokenZero's cascade can route to it, and the gateway warns in X-TokenZero-Warning until you do. | 0% |
| medium | apps/api/src/scraper/scrapeURL/transformers/llmExtract.ts:860 | "gpt-5" retires on 2026-12-11 The provider announced on 2026-06-11 that this model retires on 2026-12-11 (46 days). Recommended replacement: gpt-5.6-sol. Fix: Move to gpt-5.6-sol (eval first); TokenZero's cascade can route to it, and the gateway warns in X-TokenZero-Warning until you do. | 0% |
| low | examples/gemini-2.5-screenshot-editor/cli.py:287 | LLM call inside a loop Per-item calls repeat the full prompt prefix for every element. If items are independent and latency-tolerant, the provider Batch API is 50% cheaper, and OpenAI Flex processing (`service_tier: "flex"`) gives the same 50% on ordinary calls without restructuring; if the prefix is shared, caching pays off immediately. Fix: Batch where possible, or set `service_tier: "flex"` on OpenAI calls that can wait; otherwise keep the shared prefix cache-formatted (TokenZero does this automatically). | 25% |
| low | examples/claude-3.7-stock-analyzer/claude-3.7-stock-analyzer.py:127 | LLM call inside a loop Per-item calls repeat the full prompt prefix for every element. If items are independent and latency-tolerant, the provider Batch API is 50% cheaper, and OpenAI Flex processing (`service_tier: "flex"`) gives the same 50% on ordinary calls without restructuring; if the prefix is shared, caching pays off immediately. Fix: Batch where possible, or set `service_tier: "flex"` on OpenAI calls that can wait; otherwise keep the shared prefix cache-formatted (TokenZero does this automatically). | 25% |
| low | examples/claude_stock_analyzer/claude_stock_analyzer.py:127 | LLM call inside a loop Per-item calls repeat the full prompt prefix for every element. If items are independent and latency-tolerant, the provider Batch API is 50% cheaper, and OpenAI Flex processing (`service_tier: "flex"`) gives the same 50% on ordinary calls without restructuring; if the prefix is shared, caching pays off immediately. Fix: Batch where possible, or set `service_tier: "flex"` on OpenAI calls that can wait; otherwise keep the shared prefix cache-formatted (TokenZero does this automatically). | 25% |
| low | examples/openai_swarm_firecrawl_web_extractor/main.py:61 | "gpt-4o" retires on 2027-01-14 The provider announced on 2026-10-14 that this model retires on 2027-01-14 (80 days). Recommended replacement: gpt-6-luna. Fix: Move to gpt-6-luna (eval first); TokenZero's cascade can route to it, and the gateway warns in X-TokenZero-Warning until you do. | 0% |
| low | examples/openai_swarm_firecrawl/main.py:24 | "gpt-4o-mini" retires on 2027-01-14 The provider announced on 2026-10-14 that this model retires on 2027-01-14 (80 days). Recommended replacement: gpt-6-luna. Fix: Move to gpt-6-luna (eval first); TokenZero's cascade can route to it, and the gateway warns in X-TokenZero-Warning until you do. | 0% |
| info | examples/gemini-2.0-crawler/gemini-2.0-crawler.py:58 | Unrecognised model id "gemini-2.0-flash" Not in the current pricing table: it may be retired or renamed. Retired models return errors or are silently remapped by some providers. Fix: Check the provider model list; TokenZero flags unpriced models in `X-TokenZero-Warning`. | 0% |
| info | examples/claude3.7-web-crawler/claude3.7-web-crawler.py:39 | Unrecognised model id "claude-3-7-sonnet-20250219" Not in the current pricing table: it may be retired or renamed. Retired models return errors or are silently remapped by some providers. Fix: Check the provider model list; TokenZero flags unpriced models in `X-TokenZero-Warning`. | 0% |
| info | examples/claude_stock_analyzer/claude_stock_analyzer.py:127 | Unrecognised model id "claude-3-5-sonnet-20240620" Not in the current pricing table: it may be retired or renamed. Retired models return errors or are silently remapped by some providers. Fix: Check the provider model list; TokenZero flags unpriced models in `X-TokenZero-Warning`. | 0% |
Fix all of it with one line
OPENAI_BASE_URL=https://tokenzero.sh/v1 ANTHROPIC_BASE_URL=https://tokenzero.sh
Keys pass through untouched. Cache formatting and exact caching are on by default; cascade routing stays opt-in. How it works