Proxy error · 502

502 Bad Gateway

A 502 means a server acting as a go-between got an invalid answer, or none, from the server behind it. With a proxy in the path there are at least two go-betweens, and either one can send it.
Whose fault is it?

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
With a proxy in the path

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.

The key question

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 Server header 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 ProxyError mentioning 502 is the proxy. A Response with status_code == 502 over HTTPS is the site.
  • The error page names its server. A CDN-branded page or a Server: cloudflare header is the site side.
  • Load the site without the proxy. If it 502s there too, it is down for everyone.
Cheapest first

Fixes, in the order to try them

  1. 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
  2. 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
  3. 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 nothing
  4. 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 some time
  5. 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.

    Costs money
Per tool

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
terminal
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 failed
Python Requests
who.py
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
spiders/site.py
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
who.py
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
who.mjs
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 Tunneling

The 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.

Before you buy anything

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.

The meter

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.

From the metering section of our terms of service.

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.

502, asked often

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.

The community layer

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 Discord

4,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.

Join the Discord4,200+ monkeys, free to lurk