Mobile Proxy for Firecrawl (Cloud & Self-Hosted)
Firecrawl ships its own proxy layer on the cloud API, and a clean env-var hook for your own proxy when you self-host. Here is how the built-in tiers work, where the hosted product stops, and how to put a self-hosted instance behind a dedicated 4G/5G carrier IP.
Quick Answer
On cloud Firecrawl you pick a managed proxy tier with the proxy parameter: basic, enhanced (formerly documented as stealth), or auto. You cannot point the hosted API at your own proxy. To route Firecrawl through your own mobile proxy, self-host it and set PROXY_SERVER, PROXY_USERNAME, and PROXY_PASSWORD in the instance's .env.
- →Cloud tiers: basic (1 credit), enhanced (5 credits per request), auto (the default; escalates only on failure)
- →Self-hosted: one instance-wide proxy via env vars, applied to the API and the Playwright engine
- →A dedicated carrier IP wins when you need session stickiness, a specific geo/carrier, or flat costs
Firecrawl turns URLs into LLM-ready markdown, which made it a default ingestion layer for a lot of scraping and RAG pipelines. But the crawler is only half of the reliability story; the other half is what IP the target site sees. Firecrawl acknowledges this by routing every cloud request through proxies by default, and by leaving an explicit proxy hook in the self-hosted stack. This guide covers both, and when each is the right call for the kind of web scraping workloads that hit protected targets.
Firecrawl's built-in proxy tiers (cloud)
The hosted API exposes three proxy types through the proxy request parameter, and defaults to auto if you set nothing:
basic
Standard proxies suitable for most sites. Fast. 1 credit per scrape.
enhanced
Heavier proxies for complex, protected sites. Slower. 5 credits per request.
auto
Tries basic first, retries with enhanced on failure. 1 credit if basic succeeds, 5 if enhanced is needed.
Searching for Firecrawl stealth mode? Same feature. The tier older Firecrawl material calls stealth is named enhanced in the current docs, and the documentation page for it still lives at the /features/stealth-mode URL. Selecting a tier looks like this:
curl -X POST https://api.firecrawl.dev/v2/scrape \
-H "Content-Type: application/json" \
-H "Authorization: Bearer fc-YOUR-API-KEY" \
-d '{
"url": "https://example.com",
"formats": ["markdown"],
"proxy": "auto"
}'
# Python SDK equivalent:
# doc = firecrawl.scrape('https://example.com',
# formats=['markdown'], proxy='auto')Geo targeting is a separate knob: location.country (for example DE) asks Firecrawl to use a proxy in that market. The docs list around two dozen supported countries for basic proxies at the time of writing, but enhanced proxy support is marked available only for the United States and the Netherlands. If your protected target is geo-fenced anywhere else, the built-in tiers cannot combine the strong proxy with the right location, which matters for market research that depends on seeing local prices, listings, and availability.
What cloud Firecrawl does not let you do
The hosted API's documented proxy surface is exactly two parameters: the proxy tier and location.country. There is no documented bring-your-own-proxy option for the cloud product; you choose from Firecrawl's pools, and you do not control what kind of IP (datacenter, residential, mobile) serves a given request, whether it is shared with other customers, or how long a session keeps the same address.
For most content-site scraping that is fine, and auto is a sensible default. The gap shows up on targets that score IP reputation aggressively, need a sticky identity across a login session, or serve different content per carrier and region. For those, the documented path to full IP control is running Firecrawl yourself.
Self-hosted Firecrawl + your mobile proxy
Self-hosted Firecrawl reads its configuration from a .env file in the repo root (copy the template from apps/api/.env.example). Three variables wire in your proxy, and docker-compose.yaml passes them to both the API service and the Playwright browser service, so every fetch the instance makes egresses through your carrier IP:
# .env (root of the firecrawl repo) PORT=3002 HOST=0.0.0.0 USE_DB_AUTHENTICATION=false # Your dedicated mobile proxy (full URL or host:port) PROXY_SERVER=http://proxy.mobileproxies.org:8000 PROXY_USERNAME=u_4a9c PROXY_PASSWORD=p_2X7q # Optional: skip images/media to save mobile bandwidth BLOCK_MEDIA=true
Two details from the official template are easy to miss: PROXY_SERVER accepts a full URL or a bare host:port, and the username/password lines must stay commented out if your proxy is unauthenticated. Then build and start the stack, and point your requests at the local endpoint instead of api.firecrawl.dev:
docker compose build
docker compose up
# The instance listens on http://localhost:3002
curl -X POST http://localhost:3002/v2/crawl \
-H 'Content-Type: application/json' \
-d '{ "url": "https://docs.firecrawl.dev" }'The proxy is instance-wide, not per request: rotation happens at the proxy layer. A mobileproxies.org slot rotates to a fresh carrier IP on a schedule or via one authenticated POST to the switch endpoint, so your Firecrawl config never changes. See mobile proxy with cURL for the rotation call.
When a dedicated carrier IP beats the enhanced tier
The enhanced tier is a shared, managed pool; a dedicated mobile proxy is a 4G/5G carrier IP that only you use. Which one wins depends on the target:
Reputation
A mobile IP sits behind carrier-grade NAT shared by many real subscribers, so blanket-blocking it risks blocking real users. A dedicated slot also means nobody else burns your IP's history.
Session stickiness
You decide when the IP changes. Logged-in crawls and multi-step flows keep one identity for as long as the job needs, instead of whatever the pool assigns.
Geo + carrier control
Pick the exact country and carrier your data must come from, including markets where Firecrawl's enhanced proxies are not offered.
Cost shape
Enhanced retries bill 5 credits per request. A dedicated proxy is a flat monthly rate, which is easier to model for large recurring crawls.
In practice: keep cloud Firecrawl with proxy: "auto" for broad, low-friction crawling, and run a self-hosted instance behind a dedicated carrier IP for the protected, geo-sensitive, or session-bound slice of your pipeline. That split is common in LLM training data collection and in AI agent stacks where the agent's browsing layer has to look like a real handset, not a datacenter.
Gotchas to know before you deploy
- •One proxy per instance. The env vars are read at startup and apply to everything the instance fetches. If you need different proxies for different jobs, run separate instances or split traffic upstream.
- •Auth lines stay commented if unauthenticated. The official template is explicit: do not uncomment
PROXY_USERNAME/PROXY_PASSWORDunless your proxy actually requires credentials. - •Mind mobile bandwidth. Rendering pages pulls images, fonts, and video through your proxy. Set
BLOCK_MEDIA=trueunless you need media, especially on bandwidth-metered plans. - •Self-hosting trades features for control. Firecrawl's own docs note that some scraping methods beyond basic fetch and Playwright need manual configuration on self-hosted setups. Budget time for that.
- •Respect targets. A better IP does not change your obligations. Keep request rates reasonable and follow applicable law and each site's terms.
Frequently asked questions
What happened to Firecrawl's stealth mode?
The tier once documented as stealth is now called enhanced. The current docs list three proxy types: basic, enhanced, and auto, and the documentation page for enhanced proxies still lives at the stealth-mode URL. If a tutorial tells you to set proxy to stealth, use enhanced with the current API.
Can I plug my own proxy into cloud Firecrawl?
The cloud API's documented proxy controls are the proxy tier parameter (basic, enhanced, auto) and location.country for geo targeting. There is no documented way to route hosted requests through your own proxy server. The documented path for bring-your-own-proxy is a self-hosted instance configured with the PROXY_SERVER environment variable.
Which environment variables configure a proxy in self-hosted Firecrawl?
PROXY_SERVER (a full URL like http://host:port, or just host:port), plus PROXY_USERNAME and PROXY_PASSWORD for authenticated proxies. The official .env template warns not to uncomment the username and password lines if your proxy is unauthenticated. BLOCK_MEDIA can additionally be set to skip media requests and save proxy bandwidth.
Does the self-hosted proxy apply per request or instance-wide?
Instance-wide. PROXY_SERVER, PROXY_USERNAME, and PROXY_PASSWORD are environment variables read at startup and passed by docker-compose to both the API service and the Playwright service, so every fetch the instance makes egresses through that proxy. Rotation therefore happens at the proxy layer, not in Firecrawl.
Sources
- • Firecrawl Docs - Proxies (proxy parameter, location.country, supported countries)
- • Firecrawl Docs - Enhanced Mode (basic/enhanced/auto tiers, credit costs, auto default)
- • Firecrawl Docs - Self-hosting (.env setup, PORT 3002, docker compose, /v2/crawl test)
- • Firecrawl GitHub - SELF_HOST.md (PROXY_SERVER, PROXY_USERNAME, PROXY_PASSWORD)
- • Firecrawl GitHub - apps/api/.env.example (proxy settings for Playwright, BLOCK_MEDIA)
- • Firecrawl GitHub - docker-compose.yaml (proxy env vars passed to API and Playwright services)
Related Guides
Put Firecrawl behind a real carrier IP
Dedicated 4G/5G mobile proxies with on-demand rotation. Drop the credentials into PROXY_SERVER and your self-hosted Firecrawl egresses like a real handset.