Integration · AI & workflow tools
How to use a proxy with Crawl4AI
Crawl4AI takes a proxy per crawl: pass ProxyConfig(server=…, username=…, password=…) as proxy_config on CrawlerRunConfig, and every page fetched with that config goes through it. Point server at the ARC gateway and put pool, country and session in the username; a new username in a new config gives a new exit, so one crawler instance can run several markets or sessions side by side.
Reviewed 30 Oct 2026
http://USERNAME _pool-arcfast _country-de:PASSWORD@ proxy.arcproxies.io:8000The short answer
- Set the proxy on
CrawlerRunConfig(proxy_config=…). Theproxyargument onBrowserConfigis deprecated and prints a warning. serveris scheme, host and port;usernameandpasswordare separate fields.- Crawl4AI drives Chromium, so use the
http://scheme: Chromium supports no authentication for SOCKS5 proxies. - A rejected password does not come back as a 407. In our run it ended in a 60-second navigation timeout, so check
result.successandresult.error_message.
Setup
Set up Crawl4AI with a proxy, step by step
- 01
Install Crawl4AI and its browser
crawl4ai-setupinstalls the Playwright Chromium build the crawler drives;crawl4ai-doctorchecks the installation.shell3 linespip install -U crawl4aicrawl4ai-setupcrawl4ai-doctor - 02
Crawl through the gateway and check the exit IP
Build a
ProxyConfig, attach it to the run config, and fetch an IP echo service.CacheMode.BYPASSstops Crawl4AI from answering from its own cache, which would hide whether the proxy was used.check_exit.py17 linesimport asynciofrom crawl4ai import AsyncWebCrawler, BrowserConfig, CacheMode, CrawlerRunConfig, ProxyConfigPROXY = ProxyConfig( server="http://proxy.arcproxies.io:8000", username="USERNAME_pool-arcfast_country-de_session-k3f9a1x2_sesstime-10", password="PASSWORD",)async def main(): run = CrawlerRunConfig(proxy_config=PROXY, cache_mode=CacheMode.BYPASS) async with AsyncWebCrawler(config=BrowserConfig(headless=True)) as crawler: result = await crawler.arun("https://api.ipify.org?format=json", config=run) print(result.success, result.markdown) # the exit IP, not your ownasyncio.run(main()) - 03
One session handle per crawl task, matched locale
Mint a new
_session-handle for each task and reuse the same config for every URL in it, includingarun_many(). Settinglocaleandtimezone_idon the same run config makes the browser present itself like a visitor in the exit's city. City names come from the published list, lowercased with spaces removed.task.py24 linesimport secretsfrom crawl4ai import CacheMode, CrawlerRunConfig, ProxyConfigBASE = "USERNAME_pool-arcfast_country-de" # pool + country; city and session added per taskdef run_for_task(city: str, locale: str, timezone: str) -> CrawlerRunConfig: handle = secrets.token_hex(4) # new handle, new exit IP return CrawlerRunConfig( cache_mode=CacheMode.BYPASS, locale=locale, timezone_id=timezone, proxy_config=ProxyConfig( server="http://proxy.arcproxies.io:8000", username=f"{BASE}_city-{city}_session-{handle}_sesstime-10", password="PASSWORD", ), )async def crawl_task(crawler, urls): config = run_for_task("berlin", "de-DE", "Europe/Berlin") results = await crawler.arun_many(urls, config=config) # one exit for all return [(r.url, r.status_code) for r in results if r.success] - 04
Spread independent pages over several sessions
For URLs that do not depend on each other, Crawl4AI's
RoundRobinProxyStrategycycles through a list of proxies per request. With one gateway, the list is the same server with different session handles.rotation.py14 linesimport secretsfrom crawl4ai import CrawlerRunConfig, ProxyConfigfrom crawl4ai.proxy_strategy import RoundRobinProxyStrategyproxies = [ ProxyConfig( server="http://proxy.arcproxies.io:8000", username=f"USERNAME_pool-arcfast_country-de_session-{secrets.token_hex(4)}_sesstime-10", password="PASSWORD", ) for _ in range(4)]config = CrawlerRunConfig(proxy_rotation_strategy=RoundRobinProxyStrategy(proxies))# results = await crawler.arun_many(urls, config=config) - 05
Check every result, not only exceptions
arun()returns a result object rather than raising. Treatsuccess == Falseand 429 or 5xx status codes as retryable on a fresh handle, and stop after a few attempts. If every attempt times out, test the credentials with the exit-IP check above.retry.py12 linesimport asyncioasync def fetch(crawler, url, attempts=3): for attempt in range(attempts): config = run_for_task("berlin", "de-DE", "Europe/Berlin") # fresh handle result = await crawler.arun(url, config=config) if result.success and result.status_code not in (429, 500, 502, 503): return result print(f"attempt {attempt + 1}: {result.status_code} {result.error_message}") await asyncio.sleep(5 * 2 ** attempt) raise RuntimeError(f"gave up on {url}")
Where the proxy goes in Crawl4AI
| Setting | Status | Use it for |
|---|---|---|
CrawlerRunConfig(proxy_config=…) | Current, documented | Everything: per-task sessions, per-market runs |
CrawlerRunConfig(proxy_rotation_strategy=…) | Current, documented | Independent URLs spread across several sessions |
BrowserConfig(proxy_config=…) | Older approach | Existing code; move it to the run config |
BrowserConfig(proxy="http://user:pass@…") | Deprecated, warns | Nothing new |
ProxyConfig.from_string() also parses http://user:pass@host:port, but the explicit fields avoid URL-encoding mistakes when a password contains special characters.
Sticky sessions for LLM-ready crawls
Crawl4AI renders pages in a headless browser, and a single page load opens many connections. With a rotating username those connections can leave from different exits inside one visit. Use a sticky handle per task, as above, and a new handle for the next task.
Rendered crawls are heavier than plain HTTP fetches, and every script and image counts against a per-GB balance. How much bandwidth scraping uses gives the figures to plan with, and reducing proxy bandwidth lists what to switch off.
Which ARC pool to use with Crawl4AI
- [Residential](/residential-proxies/) (
arcfast,arcultra): the default for rendered crawls of consumer sites, with country and city targeting. - [ISP](/isp-proxies/) (
arc): the lowest price per GB; ISP-registered addresses hosted in data centres, suited to large documentation or news crawls. - Both are billed per GB that never expires, so a crawl that runs once a month does not pay for idle time.
The problem
Common pitfalls
A SOCKS5 server URL
Chromium cannot authenticate to a SOCKS5 proxy, so socks5:// with a username fails. The gateway accepts HTTP on the same port with the same credentials; use http://.
Cached results that never touched the proxy
With caching enabled, a repeated URL can come from Crawl4AI's local cache. Use CacheMode.BYPASS while testing the proxy, so the result reflects a real fetch.
Tiny test pages flagged as failures
In our run, arun_many() marked the 13-character IP-echo body as unsuccessful while arun() accepted it. Use arun() for the exit-IP check and real pages for batch tests.
Waiting a minute for a credential error
A wrong password showed up as Page.goto: Timeout 60000ms exceeded. Lower page_timeout on the run config while testing, so a credential problem surfaces in seconds.
FAQ
Questions
Something not covered? Write to contact@arcproxies.io.
How do I set an authenticated proxy in Crawl4AI?
Create ProxyConfig(server="http://host:port", username="…", password="…") and pass it as proxy_config to CrawlerRunConfig. Every arun() or arun_many() call that uses that config goes through the proxy.
Is BrowserConfig(proxy=...) still supported in Crawl4AI?
It still works but is deprecated: Crawl4AI 0.9.5 converts it to a ProxyConfig and prints a warning. The documentation recommends setting the proxy on CrawlerRunConfig so each request describes its own network settings.
Can one Crawl4AI crawler use several proxy sessions at once?
Yes. The proxy belongs to the run config, so two run configs with different ARC usernames, for example two _session- handles or two countries, leave from different exits in the same crawler instance.
Does Crawl4AI support SOCKS5 proxies?
ProxyConfig.from_string() accepts socks5://host:port, but the browser Crawl4AI drives has no SOCKS5 authentication. For a gateway with a username and password, use the http:// form.
Sources & review
Last reviewed by the ARC Proxies team. Prices are read from the live catalog at build time.
Next
What people build with it
Integrations
Other ai & workflow tools
Get started
Get credentials and paste them in.
Sign up, buy a gigabyte, generate a username in the dashboard. Code WELCOME15 takes 15% off your first purchase; bandwidth never expires.