Save 5% every month: use code 5OFFSTORM at checkout
Home / Guides / 403 Forbidden

How to fix 403 Forbidden when using a proxy

A 403 through a proxy almost always comes from the website, not the proxy: the site understood the request and refused it. Check that the same URL opens in a normal browser, then fix what the site objects to, in this order: library headers, missing cookies, request pace, the exit location, and finally the IP type, moving strict sites to residential IPs.

Updated October 2026Fix proxy errors

A 403 Forbidden means the server received your request, understood it and decided not to serve it. Unlike a 401, logging in again doesn’t change the answer, and sending the same request again usually gets the same 403. Something about the request has to change.

When a proxy is involved, people assume the proxy is the cause. It rarely is. A Storm rotating or residential gateway that doesn’t recognise your IP resets the connection; it doesn’t send a 403. If you’re looking at a 403 page, the request went through the proxy, reached the website, and the website said no. The proxy changed one thing about you, the IP. Your headers, cookies, TLS client and pace are exactly what they were without it.

This guide shows how to tell who sent the 403, how to read the page it came with, and how to fix the cause, most likely first. It’s about reliable access to public pages. It doesn’t help with pages you aren’t allowed to see, and nothing here changes a 403 caused by account permissions.

Which Storm plan fits

If a site answers datacenter IPs with 403 while your headers and pace are fine, run that site through residential ports: each port exits through a home connection, up to 50 threads per port. For sites that accept datacenter traffic, rotating proxies stay the cheaper way to run many connections, with a new IP per connection on the Main gateway. Many jobs end up split: residential for the few strict sites, rotating for the rest.

Residential rotating proxies (from $19/mo): 20M+ residential IPs. Each port is one IP at a time that changes every 5 minutes, up to 50 threads per port. USA or EU. Unlimited bandwidth on every plan.

Get 5 ports for $50/mo See all residential rotating proxies plans

Before you start

  1. Log in to the member area and copy your gateway IP:PORTs. They never change; the rotation happens on our side.
  2. Add the public IP of the computer or server that will run your tool under Authorized IPs, click Save, and allow up to 15 minutes before testing. Rotating and residential proxies use IP authentication, so there is no username or password.
  3. Count your threads: the tool’s total open connections must stay within your plan (for example 40 threads on the 40-thread plan).

Fix a 403 step by step, most likely cause first

  1. Find out who sent the 403

    Run curl -v through the proxy. If the 403 is the answer to CONNECT, before any TLS handshake, a proxy refused to open the tunnel: check for another proxy in your chain and see the tunnel guide. If TLS completes and the 403 comes back for your GET, it came from the website. Look at the Server header and body: “Error 1020 Access denied” is a Cloudflare rule set by the site owner; “Access Denied” with a reference number points to another CDN firewall.

  2. Open the same URL in a normal browser, no proxy

    If it’s 403 there too, the page is restricted (login, permissions, region) and a proxy won’t help. If it opens fine, the site is reacting to your client or IP, so keep going.

  3. Replace library headers with a real browser’s

    Default User-Agents like python-requests/2.x, curl/8.x, Go-http-client or Scrapy/2.x get a 403 on many sites before anything else is checked. Send a current browser User-Agent with the Accept, Accept-Language and Accept-Encoding headers that browser sends, and Referer where a real visitor would have one. Keep the set the same for the whole session.

  4. Get the cookies a visitor would have

    Some sites set a cookie on the homepage or through JavaScript and refuse deeper pages without it. Load the homepage first in the same session and reuse its cookies. If the cookie comes from a script, a plain HTTP client can’t run it; use a browser such as Playwright for that site.

  5. Slow down

    Some sites answer heavy clients with 403 instead of 429. If the first requests work and 403s start later, it’s pace. Cap requests per site, add pauses, back off on errors. The 429 guide has retry code that applies here too.

  6. Check the exit location

    Sites that serve one region often refuse the others. Use a USA gateway for US-only sites and an EU gateway for European ones. Storm offers USA, EU, USA+EU and Worldwide (rotating); there’s no single-country or city targeting, so a site that only accepts, say, one EU country may not work.

  7. Move strict sites to residential IPs

    If headers, cookies, pace and location are right and the site still returns 403 on datacenter IPs, its firewall is scoring the IP range. Run that site through residential ports and keep threads per port low, since every thread on a port shares one IP.

  8. Still getting 403? Contact support

    Send your username, the gateway you use, the target site, your software, and the exact error, ideally the first lines of the 403 page, through the contact page. Saying whether the URL opens in a normal browser saves a round of questions.

Find the sender, then fix the request

Replace GATEWAY_IP:PORT with your gateway. The curl command shows which hop sent the 403; the Python example sends browser-like headers and visits the homepage first to pick up cookies.

curl: is the 403 from the proxy or the site?
curl -v -x http://GATEWAY_IP:PORT https://www.example.com/page -o /dev/null 2>&1 \
  | grep -E "^< HTTP|^< Server|CONNECT|SSL connection"

# "< HTTP/1.1 403" right after "CONNECT ..."   -> a proxy refused the tunnel
# "SSL connection using ..." then "< HTTP/2 403" -> the website refused the request
# "< Server: cloudflare" + "1020" in the body    -> a rule set by the site owner
Python: browser headers + homepage cookies
import requests

PROXY = "http://GATEWAY_IP:PORT"   # a 15-minute gateway or residential port keeps one IP
s = requests.Session()
s.proxies = {"http": PROXY, "https": PROXY}
s.headers.update({
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 "
                  "(KHTML, like Gecko) Chrome/131.0.6778.86 Safari/537.36",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.9",
})

home = s.get("https://www.example.com/", timeout=(10, 30))      # sets cookies
r = s.get("https://www.example.com/category/desks",
          headers={"Referer": "https://www.example.com/"}, timeout=(10, 30))
print(home.status_code, r.status_code, r.headers.get("Server"))
Scrapy: drop the default User-Agent
# settings.py
USER_AGENT = ("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
              "(KHTML, like Gecko) Chrome/131.0.6778.86 Safari/537.36")
DEFAULT_REQUEST_HEADERS = {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.9",
}
COOKIES_ENABLED = True
HTTPERROR_ALLOWED_CODES = [403]      # let your parse() log 403 pages instead of dropping them

403, 401, 407 or a reset: which one you have

  • 403 Forbidden. The website refused a request it understood. Logging in again doesn’t change it; changing the request might.
  • 401 Unauthorized. The website wants you to log in or send a valid token.
  • 407 Proxy Authentication Required. A proxy wants credentials. With Storm that only applies to private dedicated proxies used with user:pass; see the 407 guide.
  • Connection reset. On Storm rotating and residential plans, this is what an unauthorized IP gets. No status code at all. Check Authorized IPs and the 15-minute wait, as in the not-working checklist.

Some sites return 404 instead of 403 for pages they don’t want to admit exist, so a sudden wave of 404s on known URLs can be the same problem in disguise.

What a proxy changes, and what it doesn’t

HTTPS traffic through a Storm gateway runs inside a CONNECT tunnel. The gateway carries the encrypted bytes; it doesn’t rewrite your headers, cookies or TLS handshake. So the website sees a different IP and everything else exactly as your client sent it.

That matters because many 403s are about the client, not the address. If your tool announces itself as a script, a thousand different IPs will each get the same 403. Fix the client first and you’ll know whether IP type is really the issue. Some firewalls also compare the TLS handshake with the browser named in your User-Agent; a mismatch there needs a real browser, not more IPs.

Datacenter or residential: worked sizing

Use the IP type each site accepts, not one for everything:

  • Most sites, APIs and catalogues. Rotating proxies. 40 threads ($39/mo) for a single scraper, 80 ($59/mo) when a browser runs alongside it (around 10 threads per tab).
  • One or two strict retailers that 403 datacenter IPs. Add 5 residential ports ($50/mo) and run 5 to 10 threads per port on those sites only. That’s 5 home IPs at once, each rotating every 5 minutes.
  • Heavier strict-site work. 10 ports ($90/mo) or 20 ports ($160/mo); add ports rather than threads per port.

Changing plan is one click in the member area, and the unused part of the old plan is credited.

When a 403 is the right answer

Some 403s mean exactly what they say. Admin areas, pages behind a login you don’t have, content restricted by licence to certain countries, and resources a site has decided not to share with automated clients are all off limits. Rotating IPs to get past a refusal like that isn’t a fix, and it can break the site’s terms. Look for an official API or data feed, or ask the site owner for access.

Common errors and fixes

Python requests: 403 Client Error: Forbidden for urlThe site refused the request. Usually the python-requests User-Agent or missing cookies. Send browser headers and load the homepage first in the same Session.
Scrapy: Ignoring response <403 https://...>: HTTP status code is not handled or not allowedScrapy dropped the 403. Set a browser USER_AGENT, slow down, and add 403 to HTTPERROR_ALLOWED_CODES to inspect the page.
Cloudflare: “Error 1020 Access denied”A firewall rule set by the site owner matched your request. Fix headers and pace; if it persists on datacenter IPs, try residential. If it still matches, the owner has chosen to block this traffic.
curl: CONNECT tunnel failed, response 403A proxy refused the tunnel, before the site was reached. Check for another proxy in your environment and the destination port: sending email through Storm is blocked (ports 25 and 587).
First pages work, then everything is 403Pace. The site rate-limits with 403. Lower threads per site and back off on errors.
403 only on the EU (or USA) gatewayThe site is regional. Use the gateway for the region the site serves.

FAQ

Is a 403 error caused by my proxy?

Almost never. A 403 page comes from the website. A proxy can only cause it indirectly, by giving you an IP or location the site refuses.

Why do I get 403 with a proxy but not in my browser?

Your browser sends full headers, cookies and a matching TLS handshake from an IP you use every day. A script through a proxy changes the IP and often sends library headers with no cookies. Fix the headers and cookies first.

Do Storm proxies return 403 when my IP isn’t authorized?

No. Storm rotating and residential gateways reset the connection for an IP that isn’t in Authorized IPs. A 403 means the request reached the website.

Will residential proxies fix 403 errors?

When the site blocks datacenter ranges, often yes. When the 403 is about headers, cookies, pace or permissions, no. Check those first so you buy residential ports only where they help.

Can I pick a specific country with Storm to avoid geo 403s?

You can choose USA or EU (and Worldwide on rotating plans). There’s no single-country, state or city targeting.

Should I rotate IPs on every retry after a 403?

Only after you’ve changed the request. Retrying the same request from new IPs usually returns the same 403 and adds load the site already objected to.

Still have questions? Contact us here. A real person answers.

Related guides

Tool facts checked against the official documentation (October 2026): MDN: 403 Forbidden · RFC 9110: 403 Forbidden · Cloudflare: Error 1020 · Scrapy settings: USER_AGENT · Scrapy HttpErrorMiddleware. Storm Proxies facts: our plans page and refund policy.

Unlimited bandwidth. One flat monthly price.

Access is live the moment you pay, and the smallest package of each proxy type has a 24-hour money-back guarantee on your first order.