Skip to content

Selenium WebDriver 403 Forbidden Error

Problem Statement

When running Selenium WebDriver tests in Azure DevOps (or similar remote environments), you may encounter a java.io.IOException: Invalid Status code=403 text=Forbidden error. This typically occurs after Chrome updates to version 111+ and manifests in the stack trace as:

text
org.openqa.selenium.remote.http.WebSocket$Listener onError
WARNING: Invalid Status code=403 text=Forbidden
java.io.IOException: Invalid Status code=403 text=Forbidden
...

The key indicators:

  • Tests fail in CI/CD pipelines (e.g., Azure DevOps) but work locally
  • ChromeDriver and Chrome versions are 111+
  • Error involves WebSocket communication rejection (devtools_http_handler)

Root cause:
Chrome's tightened security in v111 blocks WebSocket connections from localhost origins unless explicitly allowed.


Best Solutions

Choose the most appropriate solution for your environment.

Solution 1: Allow All WebSocket Origins (ChromeOptions)

Add --remote-allow-origins=* to bypass origin restrictions.

java
ChromeOptions options = new ChromeOptions();
options.addArguments("--remote-allow-origins=*"); // Fixes 403 error
WebDriver driver = new ChromeDriver(options);

Security Note

Using * allows all origins. For production environments, specify exact origins (e.g., --remote-allow-origins=http://localhost:8080).

Solution 2: Upgrade Selenium for JDK 8+ Projects

Update to Selenium 4.9.0+ to resolve the issue natively (no flags needed).

xml
<!-- Maven dependency -->
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>4.9.0</version> <!-- Or later -->
</dependency>
Solution 3: Use Java 11+ HTTP Client

For Selenium 4.5+ with Java 11+, switch to the JDK HTTP client.

  1. Add the client dependency:
xml
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-http-jdk-client</artifactId>
    <version>4.8.1</version> <!-- Match your Selenium version -->
</dependency>
  1. Set the HTTP factory in your code:
java
System.setProperty("webdriver.http.factory", "jdk-http-client"); // Before driver init
ChromeOptions options = new ChromeOptions();
WebDriver driver = new ChromeDriver(options);
Solution 4: Update Selenide (For Selenide Projects)

Upgrade to Selenide 6.12.2+ if you use this wrapper.

xml
<!-- Maven -->
<dependency>
    <groupId>com.codeborne</groupId>
    <artifactId>selenide</artifactId>
    <version>6.12.2</version> <!-- Or later -->
</dependency>

Why These Solutions Work

  1. ChromeOptions Flag
    Explicitly allows WebSocket connections from localhost, which Chrome 111 now blocks by default.

    • Origin: ChromeDriver logs show:
      Rejected WebSocket connection. Use --remote-allow-origins...
    • Trade-off: Convenient for tests but slightly reduces security.
  2. Selenium 4.9.0+
    Addresses compatibility with Chrome’s new security model internally.
    ✅ Use if you can update dependencies freely.

  3. JDK HTTP Client
    Replaces Selenium’s default HTTP client with Java’s built-in client.
    ✅ Better HTTPS/CORS handling in Java 11 environments.

  4. Selenide Update
    Selenide bundles Selenium fixes. Version 6.12.2 incorporates these security patches.


Common Pitfalls to Avoid

  1. Version Conflicts
    Ensure Chrome, ChromeDriver, and Selenium versions are compatible. Use ChromeDriver’s compatibility matrix.

    • Test locally with System.out.println(ChromeDriver.class.getPackage().getName()).
  2. Outdated WebDriverManager
    Always update WebDriverManager for version resolution:

    java
    WebDriverManager.chromedriver().setup(); // Before creating driver instance
  3. Hardcoded Driver Paths
    Use environment variables or WebDriverManager to handle paths in Azure DevOps.


Verification Steps

  1. Confirm Chrome version in Azure logs:
    bash
    google-chrome --version # In pipeline script
  2. Validate ChromeDriver version alignment:
    java
    @BeforeTest
    public void setup() {
        System.setProperty("webdriver.http.factory", "jdk-http-client"); // If using Solution 3
        WebDriverManager.chromedriver().setup();
        ChromeOptions options = new ChromeOptions();
        if (isAzurePipeline()) options.addArguments("--remote-allow-origins=*");
        driver = new ChromeDriver(options);
    }

References