Kosh
Kosh

Reputation: 1246

Is there any way of capturing HTTP request made by Selenium webdriver with Selenium?

I want to test if the webpage is making a HTTP POST request after fill and submit the form with Selenium webdriver. I can see it with Fiddler but is it possible to capture it from my main script?

P.S. There are some simular questions here, but they are 8 years old. Perhaps something has changed over the years.

Upvotes: 1

Views: 5409

Answers (2)

olli_kahn
olli_kahn

Reputation: 167

you can check performance (network) logs via google chrome.

SO link: https://stackoverflow.com/a/27644635/3574726
documentation: https://developer.chrome.com/docs/chromedriver/logging/performance-log

and parse logs to find if needed POST is present there

Upvotes: 1

Daniel Oliveira
Daniel Oliveira

Reputation: 131

If you're using python, there's the selenium-wire library:

Selenium Wire works by redirecting browser traffic through an internal proxy server it spins up in the background. As requests flow through the proxy they are intercepted and captured.

A language agnostic solution is to inject some javascript to hijack the XMLHttpRequest.send method and log the request before sending. You are basically adding a decorator to XMLHttpRequest.send.

The injected javascript could be:

// Creates new variable that can be accessed on future selenium script executions
window.requests = [];

// Save original send method
XMLHttpRequest.prototype.original_send = XMLHttpRequest.prototype.send;

// Creates wrapping send method, this affects any XMLHttpRequest object
XMLHttpRequest.prototype.send = (body) => {
    // Save original callback that runs after sending request
    this.original_onreadystatechange = this.onreadystatechange;

    // Create new callback
    this.onreadystatechange = (ev) => {
        if (this.readyState === XMLHttpRequest.DONE) {
            // Stores request
            window.requests.push(
                {
                    request: body,
                    response: this.responseText,
                    status: this.status,
                    status_text: this.statusText,
                    response_url: this.responseURL
                }
            );
            // Original callback runs after storing the request
            this.original_onreadystatechange(ev);
        }
    }

    // Calls original send function
    this.original_send(body);
};

If you just need the response, you can directly change XMLHttpRequest.prototype.onreadystatechange and leave .send alone.

And if you're using python, the selenium code would be:

from pathlib import Path
from selenium import webdriver
from time import sleep

driver = webdriver.Chrome()

driver.get("http://www.google.com")

# Inject script from file
with open(Path(__file__).parent / "requests_logger.js", 'r') as f:
    script = f.read()
    driver.execute_script(script)

# Do stuff

captured_requests = None
while captured_requests is None:
    sleep(.2)
    captured_requests = driver.execute_script("return window.requests")

print(f"Injected script captured {len(captured_requests)}")
for r in captured_requests:
    print(r)

Upvotes: 0

Related Questions