10

I'm trying to get browser network logs using selenium to debug request/responses. Could you please help me to find out a way.

And I'm using selenium 3.14.0 and latest Chrome browser.

Navarasu
  • 8,209
  • 2
  • 21
  • 32
Anand S
  • 101
  • 1
  • 1
  • 4
  • 3
    For future readers, since this question is one of the first that comes up when trying to find the answer, [selenium-wire](https://pypi.org/project/selenium-wire) is what you are looking for. That way you don't need a proxy. Just thought I could save you some time searching. One more note, use `request.response.body`, not `request.body`. I had to experiment to see why my body was empty and found out the documentation needs to be updated. :) – Alexis Evelyn Mar 13 '21 at 08:06

5 Answers5

22

Using python + selenium + firefox

Don't set up a proxy unless you have to- in order to get outbound API requests I used the solution from this answer, but in python: https://stackoverflow.com/a/45859018/14244758

test = driver.execute_script("var performance = window.performance || window.mozPerformance || window.msPerformance || window.webkitPerformance || {}; var network = performance.getEntries() || {}; return network;")

for item in test:
  print(item)

You get an array of dicts.

This allows me to see all the network requests made. I'm using it to parse out a parameter from one of the requests so that I can use it to make my own requests against the API.

Using python + selenium + Chrome

EDIT: this answer got a lot of attention, here is how I'm doing it now w/Chrome (taken from undetected-chromedriver code):

chrome_options = webdriver.ChromeOptions()
chrome_options.set_capability(
                        "goog:loggingPrefs", {"performance": "ALL", "browser": "ALL"}
                    )
driver = webdriver.Chrome(options=chrome_options)


##visit your website, login, etc. then:
log_entries = driver.get_log("performance")

for entry in log_entries:

    try:
        obj_serialized: str = entry.get("message")
        obj = json.loads(obj_serialized)
        message = obj.get("message")
        method = message.get("method")
        if method in ['Network.requestWillBeSentExtraInfo' or 'Network.requestWillBeSent']:
            try:
                for c in message['params']['associatedCookies']:
                    if c['cookie']['name'] == 'authToken':
                        bearer_token = c['cookie']['value']
            except:
                pass
        print(type(message), method)
        print('--------------------------------------')
    except Exception as e:
        raise e from None

With this method you can parse out tokens, api keys, etc. that your browser is sending to the server.

grantr
  • 878
  • 8
  • 16
  • `['Network.requestWillBeSentExtraInfo' or 'Network.requestWillBeSent']` evaluates to `['Network.requestWillBeSentExtraInfo']`. If the second element of this list is actually useful then this code doesn't do what is expected. If it's not then you should omit it. – Valery Kustov Dec 20 '22 at 19:05
  • This code does exactly what I'm expecting it to do: I'm listening to the network requests the browser is sending, which includes things like API keys, tokens, etc. and parsing those tokens out so I can use them. – grantr Dec 20 '22 at 20:31
  • This code doesn't extract tokens from messages with `method` equal to `'Network.requestWillBeSent'` because it is not in the list of methods to be parsed. – Valery Kustov Dec 21 '22 at 19:39
6

Using Python and ChromeDriver

To get network logs, you need to install BrowserMobProxy as well along with selenium in python

pip install browsermob-proxy

Then we need to download the browsermobproxy zip from https://bmp.lightbody.net/.

Unzip it to any folder(For e.g. path/to/extracted_folder). This folder contains the browsermob-proxy binary file. We need to mention this path while calling Server() in python code

You need to start browser proxy and configure the proxy in chrome option of chrome driver,

from browsermobproxy import Server
from selenium import webdriver

server = Server("path/to/extracted_folder/bin/browsermob-proxy")
server.start()
proxy = server.create_proxy()

# Configure the browser proxy in chrome options
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument("--proxy-server={0}".format(proxy.proxy))
browser = webdriver.Chrome(chrome_options = chrome_options)

#tag the har(network logs) with a name
proxy.new_har("google")

Then you can navigate to page using selenium

browser.get("http://www.google.co.in")

After navigation, you can get the network logs in json format from the proxy

print(proxy.har) # returns a Network logs (HAR) as JSON 

Also before quitting the driver, stop the proxy server as well at the end,

server.stop()
browser.quit()
Navarasu
  • 8,209
  • 2
  • 21
  • 32
  • Tried this and got `Keyerror: port` Then trying again without changing anything led to `OSError: [WinError 6] The handle is invalid` – West Jun 27 '19 at 10:59
  • If you are getting error about path ... try this https://stackoverflow.com/questions/55986705/getting-error-browsermob-proxy-binary-couldnt-be-found-in-path-provided-path?noredirect=1&lq=1#comment98622994_55986705 – ar-siddiqui Feb 11 '21 at 17:53
1

Try selenium-wire, I think this is a better way which also provides undetected-chromedriver against bot detection.

hans
  • 325
  • 2
  • 9
-1

For the latest python selenium version 4.1.0, webdriver.get_log(self, log_type) only have 4 type logs

driver.get_log('browser')
driver.get_log('driver')
driver.get_log('client')
driver.get_log('server')

can't get performace log by driver.get_log function

Jane22
  • 1
-4

To get only the network logs up until the page has finished loading (no ajax/async network logs during the main usage of the page), you can get the Performance Log: http://chromedriver.chromium.org/logging/performance-log

To enable the Performance Logging for the ChromeDriver, for example,

DesiredCapabilities cap = DesiredCapabilities.chrome();
LoggingPreferences logPrefs = new LoggingPreferences();
logPrefs.enable(LogType.PERFORMANCE, Level.ALL);
cap.setCapability(CapabilityType.LOGGING_PREFS, logPrefs);
RemoteWebDriver driver = new RemoteWebDriver(new URL("http://127.0.0.1:9515"), cap);

The chromium performance-log page also links to this complete example https://gist.github.com/klepikov/5457750 which has Java and python code to get the Performance Logs.

Again, it's important to keep in mind that this will only get the network requests up until the point that the page is finished loading. After that, the driver will only return the same performance logs until the page reloads.


If you want to get network logs asynchronously throughout the usage of the page, you can use BrowserMobProxy to act as a proxy server for your Selenium driver and capture all those network requests. Then, you can get those captured requests from BrowserMobProxy's generated HAR file: https://github.com/lightbody/browsermob-proxy#using-with-selenium

// start the proxy
BrowserMobProxy proxy = new BrowserMobProxyServer();
proxy.start(0);

// get the Selenium proxy object
Proxy seleniumProxy = ClientUtil.createSeleniumProxy(proxy);

// configure it as a desired capability
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(CapabilityType.PROXY, seleniumProxy);

// start the browser up
WebDriver driver = new FirefoxDriver(capabilities);

// enable more detailed HAR capture, if desired (see CaptureType for the complete list)
proxy.enableHarCaptureTypes(CaptureType.REQUEST_CONTENT, CaptureType.RESPONSE_CONTENT);

// create a new HAR with the label "yahoo.com"
proxy.newHar("yahoo.com");

// open yahoo.com
driver.get("http://yahoo.com");

// get the HAR data
Har har = proxy.getHar();

Once you have the HAR file, it is a JSON like list of network events that you can work with.

George Pantazes
  • 1,039
  • 3
  • 12
  • 26