Integration · AI & workflow tools
How to use a proxy with LangChain document loaders
LangChain's web loaders accept a proxies dictionary, but it only reaches the synchronous requests code path. WebBaseLoader(proxies=…).load() goes through the proxy; its async methods and AsyncHtmlLoader.load() fetch with aiohttp and, in our test, went out directly. The setting that covers every path is the HTTPS_PROXY environment variable plus trust_env=True; for AsyncHtmlLoader alone, requests_kwargs={"proxy": url} also works.
Reviewed 30 Oct 2026
http://USERNAME _pool-arcfast _country-de:PASSWORD@ proxy.arcproxies.io:8000The short answer
WebBaseLoader(proxies={...})proxiesload()andlazy_load(), notaload()oralazy_load().AsyncHtmlLoader(proxies={...})stores the proxy but itsload()never uses it. Passrequests_kwargs={"proxy": url}instead.HTTPS_PROXYin the environment withtrust_env=Trueon the loader proxied every path we tested, sync and async.- These loaders live in
langchain-community, whose repository was archived on 19 June 2026. Pin the version you tested.
Setup
Set up LangChain loaders with a proxy, step by step
- 01
Install the loaders
WebBaseLoaderparses with BeautifulSoup;AsyncHtmlLoaderreturns raw HTML. Set aUSER_AGENTenvironment variable, or LangChain logs a warning on import.shell2 linespip install "langchain-community==0.4.2" beautifulsoup4export USER_AGENT="research-bot/1.0 (+https://example.com/bot)" - 02
WebBaseLoader with proxies (synchronous load)
The dictionary uses the
requestsformat: one entry per target scheme, both pointing at the gateway withhttp://. HTTPS pages still work:requestsopens a CONNECT tunnel through the proxy.web_base.py10 linesfrom langchain_community.document_loaders import WebBaseLoaderPROXY = "http://USERNAME_pool-arcfast_country-de_session-k3f9a1x2_sesstime-10:PASSWORD@proxy.arcproxies.io:8000"loader = WebBaseLoader( ["https://api.ipify.org?format=json", "https://example.com/"], proxies={"http": PROXY, "https": PROXY},)docs = loader.load() # synchronous: goes through the proxyprint(docs[0].page_content) # {"ip":"…"}: the exit, not your machine - 03
AsyncHtmlLoader: pass the proxy to aiohttp
AsyncHtmlLoader.load()runs onaiohttp, which takes a singleproxyURL per request.requests_kwargsis passed straight into eachsession.get()call, so that is where the proxy goes.async_html.py10 linesfrom langchain_community.document_loaders import AsyncHtmlLoaderPROXY = "http://USERNAME_pool-arcfast_country-de:PASSWORD@proxy.arcproxies.io:8000"loader = AsyncHtmlLoader( ["https://example.com/a", "https://example.com/b"], requests_kwargs={"proxy": PROXY}, requests_per_second=2, # concurrent requests, despite the name)docs = loader.load() - 04
One setting for every path: environment plus trust_env
With
HTTPS_PROXYset andtrust_env=True,aiohttpreads the proxy from the environment, andrequestsreads it by default. This is the option to use in a RAG pipeline that mixesload()andalazy_load().env_proxy.py10 linesimport osfrom langchain_community.document_loaders import WebBaseLoaderos.environ["HTTPS_PROXY"] = "http://USERNAME_pool-arcfast_country-de:PASSWORD@proxy.arcproxies.io:8000"os.environ["HTTP_PROXY"] = os.environ["HTTPS_PROXY"]loader = WebBaseLoader(["https://example.com/a", "https://example.com/b"], trust_env=True)docs = loader.load() # requests: proxied# async for doc in loader.alazy_load(): ... # aiohttp: proxied via trust_env - 05
Handle proxy errors without logging the password
A rejected password raises
requests.exceptions.ProxyErroron the sync path andaiohttp.ClientHttpProxyError(status 407) on the async path. Theaiohttpmessage includes the proxy URL with the password in it, so log the status, not the exception text.errors.py11 linesimport aiohttpimport requestsdef load_safely(loader): try: return loader.load() except requests.exceptions.ProxyError: raise RuntimeError("proxy refused the connection: check username and password") from None except aiohttp.ClientHttpProxyError as err: raise RuntimeError(f"proxy returned {err.status}") from None # no URL, no password
Which LangChain loader path uses the proxy
Measured with langchain-community 0.4.2 against a local proxy that logs every connection:
| Call | proxies={...} | requests_kwargs={"proxy": url} | HTTPS_PROXY + trust_env=True |
|---|---|---|---|
WebBaseLoader.load() / lazy_load() | Proxied | Breaks: requests rejects the keyword | Proxied |
WebBaseLoader.alazy_load() / aload() | Not proxied | Proxied | Proxied |
AsyncHtmlLoader.load() | Not proxied | Proxied | Proxied |
"Not proxied" fails silently: the page loads from your own IP and nothing in the result tells you. Run the IP echo check through the exact method your pipeline calls.
Rotating or sticky for RAG ingestion
Loading a list of unrelated documentation or article URLs is a natural fit for a rotating username: each connection can leave from a different exit, which spreads the load. Use a sticky username, with _session- and _sesstime-, when the URLs are steps of one browse on one site, such as paginated listings that set cookies. Rotating vs sticky sessions has the details.
The loaders do not render JavaScript. For pages that need a browser, a rendering crawler such as Crawl4AI can produce the documents instead, and its markdown output feeds a text splitter the same way.
Polite ingestion with LangChain loaders
- Keep
requests_per_secondlow; it caps concurrency, and two to five parallel requests per site is plenty for most ingestion jobs. - Check a site's robots.txt and terms before bulk loading, and stick to public pages. Building AI training data covers collection hygiene.
- Cache what you load. Re-fetching an unchanged page costs bandwidth on a per-GB plan and adds load to the site.
The problem
Common pitfalls
Trusting proxies= on the async path
The most common failure here is invisible: async methods ignore the proxies dictionary and fetch directly. Use the environment variable with trust_env=True, or test each method you call.
Using requests_kwargs on WebBaseLoader's sync path
WebBaseLoader passes requests_kwargs to both requests and aiohttp. A proxy key works for aiohttp but makes requests.get() fail, so do not use it with load().
Passwords in logs
aiohttp includes the proxy URL, credentials and all, in its error message. Catch the exception and log only its status.
An unpinned, archived package
langchain-community no longer receives maintenance. Pin the version, and re-run the proxy check whenever you upgrade anything in the stack.
FAQ
Questions
Something not covered? Write to contact@arcproxies.io.
How do I use a proxy with LangChain WebBaseLoader?
Pass proxies={"http": url, "https": url} for load(). For async methods, set HTTPS_PROXY in the environment and create the loader with trust_env=True; that combination proxied every path in our test.
Why does AsyncHtmlLoader ignore my proxies argument?
AsyncHtmlLoader.load() fetches with aiohttp, and the proxies dictionary is only applied to an internal requests session that load() does not use. Pass requests_kwargs={"proxy": url} or use HTTPS_PROXY with trust_env=True.
Is langchain-community still maintained?
LangChain announced the sunset of langchain-community in May 2026 and the repository was archived on 19 June 2026. The package still installs; pin the version and plan for a replacement.
Can LangChain loaders use a SOCKS5 proxy?
Not without extra packages: requests needs requests[socks] and aiohttp needs a connector such as aiohttp-socks. The ARC gateway serves HTTP on the same port with the same credentials, so the http:// form needs nothing extra.
Sources & review
Last reviewed by the ARC Proxies team. Prices are read from the live catalog at build time.
- [1]LangChain: WebBaseLoader reference: proxies, requests_kwargs, trust_env
- [2]LangChain (GitHub): Sunsetting langchain-community (issue #674)
- [3]aiohttp: Client advanced usage: proxy support and trust_env
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.