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 ​