502 Bad Gateway
It depends on when it arrived. On the CONNECT it is the proxy path; inside the tunnel it is the site.
- Usually from
- Either: the proxy path or the site’s load balancer
- Try first
- Check whether it came on the CONNECT or inside the tunnel
What a 502 means through a proxy
A forward proxy sends 502 when it cannot get a usable reply from where it was sending you: the target refused or reset the connection, or the exit could not reach it. On the residential gateway your request leaves through a home connection, and those drop now and then.
Sites run go-betweens of their own. A CDN or load balancer in front of a site sends 502 when the application behind it crashes or returns garbage. That 502 has nothing to do with your proxy.
For an HTTPS target the two are easy to tell apart. A proxy’s 502 is the answer to CONNECT, so no tunnel opened. A 502 read as a response inside the tunnel came from the site side.
Your credentials, the proxy, or the target?
It depends on when it arrived. On the CONNECT it is the proxy path; inside the tunnel it is the site.
Your credentials
Not the cause. Bad credentials give a 407.
The proxy
When the 502 answers the CONNECT, the gateway could not reach the target through the exit it picked. Often one bad exit; a retry leaves from another.
The target site
When the 502 comes back as a response inside the tunnel, the site’s own servers are failing. The body and the
Serverheader usually show whose error page it is.
How to tell
- In curl,
%{http_connect}is the proxy's answer and%{http_code}is the site's. 502 in the first means the proxy; 200 then 502 means the site. - In Python Requests, a
ProxyErrormentioning 502 is the proxy. AResponsewithstatus_code == 502over HTTPS is the site. - The error page names its server. A CDN-branded page or a
Server: cloudflareheader is the site side. - Load the site without the proxy. If it 502s there too, it is down for everyone.
Fixes, in the order to try them
- Costs nothing
Retry once or twice, with a pause
On rotating residential a retry leaves through a different exit, and a proxy-side 502 is usually one exit failing. Keep it to one or two tries.
- Costs nothing
Check whether the site is down
Open it without the proxy. If it fails there too, wait it out. Nothing on your side fixes someone else’s outage.
- Costs nothing
Check the status bot
Incidents on our side are posted by the status bot in Discord. If it is quiet and the proxy-side 502s keep coming, post the curl output in the Discord.
- Costs some time
Log the host with every 502
If one host 502s and the rest are fine, the trouble is between the proxy network and that host, and whoever helps you in Discord will want the hostname.
- Costs money
Try the target through a static IP
If rotating residential gives scattered 502s on one target, an ISP or datacenter IP has a steadier path to it. Worth paying for only if the target accepts that kind of address.
See the real status and headers
Each sample separates the proxy’s answer to CONNECT from the site’s response, which is the whole question with a 502.
curl
curl -s -o /dev/null -x http://USER:[email protected]:8000 \
-w 'CONNECT answered: %{http_connect}\nsite answered: %{http_code}\n' \
https://example.com/
# CONNECT answered: 502 the proxy could not reach the site
#
# CONNECT answered: 200
# site answered: 502 the site's own servers failedPython Requests
import requests
PROXY = "http://USER:[email protected]:8000"
try:
r = requests.get("https://example.com/", proxies={"http": PROXY, "https": PROXY}, timeout=30)
except requests.exceptions.ProxyError as err:
print("proxy side:", err)
else:
print("site side:", r.status_code, r.headers.get("server"), r.headers.get("via"))Scrapy
import scrapy
from scrapy.core.downloader.handlers.http11 import TunnelError
class SiteSpider(scrapy.Spider):
name = "site"
handle_httpstatus_list = [502]
start_urls = ["https://example.com/"]
def start_requests(self):
for url in self.start_urls:
yield scrapy.Request(url, errback=self.on_error)
def parse(self, response):
if response.status == 502:
self.logger.warning("site 502 at %s, server=%s", response.url, response.headers.get("Server"))
def on_error(self, failure):
if failure.check(TunnelError):
self.logger.warning("proxy 502 on CONNECT: %s", failure.value)The retry middleware retries a 502 on its own first, so parse sees it only once the retries are used up.
Playwright
from playwright.sync_api import Error, sync_playwright
PROXY = {"server": "http://resi.proxymonkey.io:8000", "username": "USER", "password": "PASS"}
with sync_playwright() as p:
browser = p.chromium.launch(proxy=PROXY)
page = browser.new_page()
try:
response = page.goto("https://example.com/")
print("site side:", response.status, response.headers.get("server"))
except Error as err:
print("proxy side:", err.message.splitlines()[0])
browser.close()net::ERR_TUNNEL_CONNECTION_FAILED is Chromium’s name for a CONNECT that did not get a 200.
Node.js
import { fetch, ProxyAgent } from "undici";
const dispatcher = new ProxyAgent("http://USER:[email protected]:8000");
try {
const res = await fetch("https://example.com/", { dispatcher });
console.log("site side:", res.status, res.headers.get("server"));
} catch (err) {
console.error("proxy side:", err.cause?.message ?? err);
}
// proxy side: Proxy response (502) !== 200 when HTTP TunnelingThe samples use the residential gateway, resi.proxymonkey.io:8000. For an ISP or datacenter IP, use USER:PASS@IP:PORT for the address you rented. Your dashboard lists the host and port for every order, and where it differs from this page, the dashboard is right.
Will a different proxy line fix it?
When switching helps
When the 502s come from flaky residential exits on a target that accepts other addresses, a static ISP or datacenter IP gives a steadier path to it.
When it will not
A 502 from the site’s own load balancer is the site failing. Every line sees it until the site is fixed.
Is a failed request billed?
We bill for request bytes and response bytes, including headers and protocol overhead on the tunnelled connection. Connections that fail before transferring data are not billed. Retries that you initiate are billed and appear as separate entries in your usage log.
The terms say connections that fail before transferring data are not billed, and that request and response bytes are. They do not say which side of that line a proxy’s own 502 falls on, so look for the row in your usage log and ask in Discord if you think it should not be there. A 502 page served by the site came back through the tunnel like any other response.
Residential is billed per GB of that traffic. ISP and datacenter addresses are charged per IP for their term, and where a plan includes a traffic allowance, traffic past it is billed per GB under the same rule. The usage log in your dashboard has one row per request with bytes in, bytes out and cost, so you can look up the failed request yourself.
Questions people ask about a 502
Is a 502 my fault?
Almost never. Your credentials worked, or you would have a 407. A 502 means one of the go-betweens got a bad reply from the server behind it: the proxy from the target, or the site’s load balancer from its own servers.
Should I retry a 502?
Once or twice, with a pause. On rotating residential the retry leaves through another exit. The terms bill retries you initiate as separate entries, so do not loop forever.
What is the difference between 502 and 504?
A 502 means the go-between got a bad reply. A 504 means it got no reply in time. Either can come from the proxy or from the site’s own infrastructure, and the CONNECT check tells them apart the same way.
Why do I only get 502 on one site?
Usually the path from the proxy network to that host is the problem, or the host is refusing connections from the exit. Post the hostname and the curl output in the Discord so someone can look at it.
Errors that travel with this one
- 503
503 Service Unavailable
Somebody is overloaded, down for maintenance, or turning you away. The body and Retry-After tell you which.
Work it out → - TIMEOUT
Connection timeout
Nothing came back in time. Find out which leg stalled before you raise the limit.
Work it out → - ECONNREFUSED
Connection refused
Something said no before any HTTP happened. Usually the host or port you gave for the proxy.
Work it out →
Still stuck on a 502?
Paste your error in the Discord: the full message plus the command or the few lines that set up the proxy, with the password taken out. Someone there has seen it before.
Join the Discord4,200+monkeys in the Discord
Help from humans
Post your error, get an answer. Usually in minutes, usually from someone who has hit the same wall.
A status bot that tells on us
Pool health, incidents and maintenance posted automatically. Including the bad days.
Deals and free traffic
Bonus GB drops, early access to new pools, and the occasional giveaway for a good bug report.