How to Fix a 403 Forbidden Error
Find out whether the site, its firewall or your proxy refused you, then apply the matching fix.
Updated
TL;DR
403 Forbidden means the server understood your request and refused it, and the website or its CDN firewall sends most 403s. On a VPN or proxy, turn it off and reload once; if the page opens, keep it off for that site.
What a 403 looks like on screen and in the terminal
Each layer words its refusal differently, so the text shows who sent it. Many sites replace these default server pages with their own.
| Where | What you see |
|---|---|
| Chrome, when the 403 has an empty body | Access to example.com was denied / You don't have authorization to view this page. / HTTP ERROR 403 |
| nginx default page | 403 Forbidden / nginx/VERSION |
| Apache httpd default page | Forbidden / You don't have permission to access this resource. |
| Django site, failed CSRF check | Forbidden (403) / CSRF verification failed. Request aborted. |
| curl with --fail | curl: (22) The requested URL returned error: 403 |
| Python urllib | urllib.error.HTTPError: HTTP Error 403: Forbidden |
| curl, when the proxy refuses the request | CONNECT tunnel failed, response 403 |
Why this happens
The site, or the firewall in front of it, decided to refuse this request.
Owners set rules on IP ranges, countries, paths and methods. A common match for VPN users is the IP range itself: AWS WAF's Anonymous IP list, which owners can switch on, blocks VPNs, proxies and hosting providers.
Diagnose your 403 first
These four checks show which layer refused you before you change anything.
Read the 403 page; a Ray ID or CDN branding points to a firewall rule, a bare nginx or Apache page to the server.
Open another page on the same site; if only one path is refused, a rule or file permission covers that path.
Load a page, then submit its form; if only the submit gets 403, a CSRF check or a method rule refused it.
In a script, print the response headers; x-ratelimit-remaining: 0 or Retry-After means a rate limit, which GitHub's API can send as 403.
Solutions ranked by effectiveness
Pick the fix that matches where the 403 appears: a browser, a proxied script or your own code.
- Most common fix
Keep the VPN off and contact the site
In a browser, a site that refuses VPN traffic does it on purpose, so leave the VPN off there rather than switching servers or countries, which only goes around the owner's choice.
Turn off proxy extensions and the system proxy too, since they also change your IP.
If the page says CSRF verification failed, allow cookies, reload the form and resend.
If the 403 stays, send the site the time and any reference ID it shows.
- Check next
Fix or drop the proxy for this site
If the proxy refuses the tunnel with 403, fix the flags or targeting values in the username. If only the proxied request gets 403, the site refuses the proxy, so stop using it there.
URL="https://example.com/page" curl -sS -o /dev/null -w 'direct: %{http_code}\n' "$URL" curl -sS -o /dev/null -p -w 'proxy: CONNECT %{http_connect}, site %{http_code}\n' \ -x "http://USERNAME:PASSWORD@proxy.geonode.io:9000" "$URL" - For developers
Send the login and token the site expects
When a browser gets in but your script gets 403 even without a proxy, the site checks for something the browser sends and your script does not.
Print the 403 body first; RFC 9110 lets servers state the reason there.
Send the documented login or API token with every request.
For a Django form, copy the csrftoken cookie into an X-CSRFToken header.
Over HTTPS, also send an Origin or Referer header naming the same site.
Stop the 403 from coming back
For scripts and scheduled jobs that go back to the same site, these habits keep each run inside what the owner allows.
Read robots.txt and the site's terms before the first run; robots rules alone are not permission.
Ask the owner for API access or an allowlist entry, naming your tool, pages and request rate.
Keep one session with its cookies for the whole job, so logins and CSRF tokens stay valid.
Log the status, headers and body of every 403, so you can show the owner what was refused.
Related errors
Learn more
FAQ
Make allowlisting easy for owners
Ask the owner to allow one Dedicated ISP IP that no one else uses.


