Skip to content

403 Forbidden: The Bane of Web Scrapers (And How to Avoid It)

If you‘ve ever tried to scrape data from websites, you‘ve almost certainly run into the dreaded "403 Forbidden" error at some point. This HTTP status code indicates that the server understood your request, but is refusing to fulfill it. In other words, you don‘t have permission to access the resource you requested.

For web scrapers, 403 errors are a constant headache. Websites use them to prevent unauthorized access to pages and to block traffic that appears to come from bots or scrapers rather than human users. Getting a 403 response can bring your web scraping project to a screeching halt.

But don‘t despair! While 403 errors can be frustrating, they are not insurmountable. With the right techniques, it‘s possible to avoid triggering 403s and keep your web scraper running smoothly. In this guide, we‘ll dive into the causes of 403 errors and explore strategies to prevent them. Let‘s get started!

Why Web Scrapers Encounter 403 Errors

There are a few main reasons why a web scraper might receive a 403 Forbidden response from a website:

  1. Requesting a restricted resource: Some pages are simply off-limits to unauthorized users. For example, trying to access a page that requires being logged in, like a user dashboard, will often result in a 403 error if you don‘t have a valid session.

  2. Missing authentication: Many websites require some form of authentication, such as logging in with a username and password, to access certain pages. If your web scraper doesn‘t provide the necessary authentication credentials, it will likely get a 403 response.

  3. Bot detection: Websites often employ various techniques to detect and block traffic that appears to come from bots or scrapers. If a site believes your web scraper is an automated tool rather than a human user, it may respond with a 403 error.

  4. Anti-bot systems: Some websites use dedicated anti-bot solutions like Cloudflare, Imperva, or PerimeterX to protect against scraping and other automated threats. These systems analyze traffic patterns and block requests that seem suspicious, often returning 403 errors.

To successfully scrape websites, we need ways to avoid these issues and convince sites that our web scraper is a legitimate, authorized user. Fortunately, there are several approaches we can take. Let‘s look at some of the most effective tactics.

Providing Authentication

If a website requires logging in to access the content you want to scrape, you‘ll need to include authentication in your web scraping process. This typically involves two steps:

  1. Inspecting the login process: Use your browser‘s developer tools to observe the network traffic when logging in to the site manually. Look for the request that submits the login credentials and note the URL, request method, headers, and request body. You‘ll need to replicate this request in your web scraper.

  2. Logging in programmatically: Use a library like Python‘s Requests or Node.js‘s Axios to send a login request mimicking the one you observed. Capture any cookies the site returns, as these often contain session tokens needed to authenticate subsequent requests. Include these cookies in the headers of your web scraping requests to maintain a valid login session.

Here‘s an example of programmatically logging into a site using Python and Requests:

import requests

# Start a new session
session = requests.Session() 

# Send a POST request to the login URL with the necessary credentials
login_data = {
    ‘username‘: ‘my_username‘,
    ‘password‘: ‘my_password‘,
response =‘‘, data=login_data)

# The session now contains the cookies needed to authenticate future requests
response = session.get(‘‘)

By authenticating your web scraper and including the necessary cookies and headers in your requests, you can avoid 403 errors caused by missing permissions.

Stealth Techniques

Of course, logging in is not always enough. Websites are engaged in a constant cat-and-mouse game with web scrapers, looking for signals that distinguish bots from human users. To avoid getting blocked, web scrapers need to blend in by mimicking human behavior as closely as possible.

Some key stealth techniques include:

  • Rotating user agents: The user agent is a string that identifies the client making a request. Using the same user agent for all requests is a dead giveaway that traffic is coming from a bot. Instead, maintain a pool of user agent strings and randomly select a different one for each request.

  • Rotating IP addresses: Sending a high volume of requests from a single IP address is another red flag for bot detection systems. Use a proxy service to route requests through a variety of IP addresses. For best results, choose a provider that offers a large pool of residential IPs.

  • Randomizing request patterns: Humans don‘t browse websites in a perfectly regular way. They pause, change pages erratically, and vary the time between requests. Introduce random delays between your web scraping requests and avoid crawling sites in a perfectly predictable pattern.

  • Handling CAPTCHAs: Some websites will present CAPTCHAs when they suspect bot activity. CAPTCHAs can be tricky for web scrapers to solve automatically. If you encounter them frequently, you may need to use a CAPTCHA solving service that utilizes human workers to complete the challenges on your scraper‘s behalf.

Here‘s an example of a stealthier request in Python using a random user agent and delays:

import requests
import random
import time

# List of user agent strings
user_agents = [    
    ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36‘,
    ‘Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36‘,
    ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36‘,  

# Randomize user agent 
headers = {‘User-Agent‘: random.choice(user_agents)}

# Introduce a random delay of 1-5 seconds
time.sleep(random.randint(1, 5))

# Send the request
response = requests.get(‘‘, headers=headers)

By taking steps to make your web scraper‘s traffic look as "human" as possible, you can significantly reduce the risk of encountering 403 errors and other obstacles.

Undetectable Automation

For the stealthiest possible web scraping, you may want to use a full browser automation tool like Puppeteer or Playwright. These tools run an actual browser (Chrome or Firefox) programmatically, allowing you to interact with websites in a way that‘s very hard to distinguish from real human users.

Browser automation tools can be configured for maximum stealth. For example, you can set them to block JavaScript fingerprinting code, mask the telltale signs of automation in Navigator objects, and randomize viewport dimensions. By controlling a real browser, you also get automatic handling of cookies, headers, redirects and other aspects of HTTP that basic web scraping libraries don‘t manage for you.

The downside of browser automation is that it‘s more resource intensive and slower than sending simple HTTP requests with a library like Requests or Axios. The trade-off in performance may be worth it, however, for sites that are particularly aggressive in blocking scrapers.

Here‘s a basic example of using Puppeteer in Node.js to visit a page in headless Chrome:

const puppeteer = require(‘puppeteer‘);

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  // Configure the browser for stealth (omitted for brevity)

  await page.goto(‘‘);

  // Scrape data from the page...

  await browser.close();

With some additional configuration, tools like Puppeteer can be a powerful way to automate scraping while avoiding detection.


Encountering 403 errors is an inevitable part of web scraping, but with the right approach they don‘t have to derail your projects. By understanding why 403s happen and taking steps to avoid triggering them – through authentication, stealth techniques, and undetectable automation – you can keep your web scraper running smoothly.

The most effective approach will vary depending on the specific websites you‘re targeting. Some may require only simple request headers to avoid 403s, while others may necessitate a full browser automation setup. The key is to start with basic techniques and add more sophisticated layers of stealth as needed based on the obstacles you encounter.

If the ever-evolving challenge of avoiding 403s and other anti-scraping measures feels daunting, you may want to consider utilizing an off-the-shelf web scraping API rather than building and maintaining your own scraping infrastructure. Services like ScrapingBee and ScraperAPI offer battle-tested scrapers with built-in 403 avoidance that can save you substantial development time.

Whether you choose to roll your own web scraper or use a pre-built solution, the important thing is to not let 403 errors stop you from getting the data you need. With a bit of persistence and the right tools in your kit, you can keep your web scraper running in the face of any anti-bot countermeasures. Happy scraping!

Join the conversation

Your email address will not be published. Required fields are marked *