n8n has two ways to route traffic through a proxy: set it per-request inside the HTTP Request node's options, or set it globally for the whole instance with the standard HTTP_PROXY / HTTPS_PROXY environment variables. Per-node is right when only some workflows need a proxy; global is right when everything should route through one. Both take about a minute once you know the gotchas.
Option 1: per-request in the HTTP Request node
This is the usual choice — you proxy the specific requests that need it (usually scraping or geo-restricted calls) and leave the rest direct. In the HTTP Request node, open Options → Proxy and enter your proxy URL with credentials inline:
http://USER:[email protected]:7777That is the whole configuration for that node. Every request the node makes now exits through the proxy. If your provider gives a rotating endpoint, each request automatically gets a fresh IP; if you need the same IP across a multi-step workflow, use a sticky-session endpoint instead. Duplicate the node or set the proxy on each HTTP Request node that needs it.
Option 2: globally with environment variables
To route the entire n8n instance through a proxy, set standard proxy environment variables where n8n runs — in your Docker Compose, systemd unit or shell:
HTTP_PROXY=http://USER:[email protected]:7777
HTTPS_PROXY=http://USER:[email protected]:7777
NO_PROXY=localhost,127.0.0.1Restart n8n and every outbound HTTP request — from every node — routes through the proxy. The NO_PROXY line matters: without it, n8n's own internal and localhost calls also try to go through the proxy, which breaks webhooks and local integrations. This global approach is cleaner for a scraping-focused instance where you want everything proxied by default.
The gotchas that actually trip people up
The n8n community forum is full of "my proxy config doesn't work" threads, and the causes are almost always one of these:
| Symptom | Cause | Fix |
|---|---|---|
| Proxy ignored entirely | Env vars set in the wrong place (shell vs container) | Set them where the n8n process actually runs — inside the Docker container's environment, not the host shell |
| Webhooks break after adding proxy | Global proxy catches localhost calls | Add NO_PROXY=localhost,127.0.0.1,n8n |
| Auth fails / 407 | Special characters in password not URL-encoded | URL-encode the credentials in the proxy string |
| HTTPS sites fail, HTTP works | Only HTTP_PROXY set | Set HTTPS_PROXY too — most targets are HTTPS |
The single most common one is the first: in a Dockerized n8n, environment variables have to be passed to the container (in docker-compose.yml under environment:), not exported in your terminal where they never reach the process.
Testing that the proxy actually works
Before pointing a proxy at your real target, confirm it is routing as expected — this saves hours of debugging a workflow that silently ignored the config. Add a temporary HTTP Request node (or a manual execution) that calls an IP-echo endpoint like https://ipinfo.io/ip through the proxy, and check that the returned IP is the proxy's exit, not your server's. Run it twice: on a rotating endpoint you should see two different IPs, confirming rotation; on a sticky endpoint the same IP twice. If the echoed IP is still your server's address, the proxy is being ignored — recheck where the env vars are set (container vs host) or that the node's proxy field is populated. This two-minute test is the difference between "my scraper works" and "my scraper has been hitting the target from one bare IP the whole time and I just got banned."
Why you need a proxy in n8n at all
Most people reach for this because an n8n workflow that scrapes or hits an API at volume starts getting blocked or rate-limited — the target sees many requests from your server's single IP and throttles it. Routing through a proxy, especially a rotating one, spreads those requests across many IPs so no single address trips a limit. For scraping defended sites you want residential IPs that look like real users; for high-volume calls to tolerant targets, cheaper datacenter IPs are fine. Match the network to how hard the target blocks — we break down the choice in what is a rotating proxy.
Beyond proxying: when the HTTP node isn't enough
A proxy fixes the IP problem, but the HTTP Request node still only sees raw HTML — it can't render JavaScript or parse messy pages into clean data. When your n8n scraping workflow hits a JS-heavy site or you're tired of writing HTML-parsing expressions, point the HTTP Request node at a scraping API instead of the target directly: you get back clean Markdown or structured JSON, with the proxy, rendering and anti-block handled server-side. One HTTP Request node, a JSON body with the URL, and the response is ready-to-use data — no proxy config, no parsing. For workflows that discover and collect across whole sites, the same endpoint offers crawl and map, and AI-driven n8n flows can call the web-data API as a tool. That turns a fragile scraping workflow into a reliable one, which is usually why people were fighting the proxy config in the first place.