82

I'm using Selenium to run tests in Chrome via the Python API bindings, and I'm having trouble figuring out how to configure Chrome to make the console.log output from the loaded test available. I see that there are get_log() and log_types() methods on the WebDriver object, and I've seen Get chrome's console log which shows how to do things in Java. But I don't see an equivalent of Java's LoggingPreferences type in the Python API. Is there some way to accomplish what I need?

Community
  • 1
  • 1
msridhar
  • 2,846
  • 4
  • 22
  • 23
  • The answers here no longer work for Selenium 4. The current answer is at https://stackoverflow.com/questions/66465158/get-info-and-warnings-consol-logs-from-chrome-with-selenium-from-specific-comman – Ken Shirriff Aug 26 '23 at 02:28

4 Answers4

141

Ok, finally figured it out:

from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

# enable browser logging
d = DesiredCapabilities.CHROME
d['loggingPrefs'] = { 'browser':'ALL' }
driver = webdriver.Chrome(desired_capabilities=d)

# load the desired webpage
driver.get('http://foo.com')

# print messages
for entry in driver.get_log('browser'):
    print(entry)

Entries whose source field equals 'console-api' correspond to console messages, and the message itself is stored in the message field.

Starting from chromedriver, 75.0.3770.8, you have to use goog:loggingPrefs instead of loggingPrefs:

d['goog:loggingPrefs'] = { 'browser':'ALL' }
Perdu
  • 187
  • 1
  • 6
msridhar
  • 2,846
  • 4
  • 22
  • 23
  • 4
    Hm. Investigating how to do this with chrome_options after trying this out and getting: `/usr/lib/python2.6/site-packages/selenium/webdriver/chrome/webdriver.py:54: DeprecationWarning: Desired Capabilities has been deprecated, please user chrome_options. warnings.warn("Desired Capabilities has been deprecated, please user chrome_options.", DeprecationWarning)` – kiminoa Jan 07 '15 at 06:32
  • I use `webdriver.Remote` with a capability of `browserName="chrome"` to instantiate my driver, and it keeps telling me `AttributeError: 'WebDriver' object has no attribute 'get_log'`. When I go to the source, I'm struggling to find the `get_log` implementation used in this lovely answer. I suspect I've gone horribly astray... somewhere. Wish I knew where! http://selenium.googlecode.com/svn/trunk/docs/api/py/search.html?q=get_log&check_keywords=yes&area=default – kiminoa Jan 07 '15 at 07:20
  • 2
    @kiminoa I had this issue with selenium `2.33.0`, upgrade to `2.45.0` fixed it. – Equidamoid Mar 03 '15 at 11:55
  • 1
    Is there something similar for IE ? I already checked https://code.google.com/p/selenium/wiki/DesiredCapabilities. Looks like there isn't – binithb Nov 06 '15 at 08:50
  • 1
    @binithb no idea; you probably want to ask a separate top-level question – msridhar Nov 06 '15 at 20:06
  • 5
    Looks like I can comment out `d['loggingPrefs'] = { 'browser':'ALL' }` and get same results. Also, any way for console logs to not just be `'level':'SEVERE'` ? – Shane Jan 19 '16 at 02:06
  • 1
    @Shane you need to wait a few seconds with `time.sleep(5)` or your browser will quit without console.log executed. This is my case. – pony Mar 27 '20 at 12:22
  • 1
    you just saved my remaining sanity, thanks man. – Seaver Olson Oct 20 '21 at 05:20
17

To complete the answer: starting from chromedriver 75.0.3770.8, you have to use goog:loggingPrefs instead of loggingPrefs.

See Chromedriver changelog: http://chromedriver.chromium.org/downloads or this bug: https://bugs.chromium.org/p/chromedriver/issues/detail?id=2976

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
Perdu
  • 187
  • 1
  • 6
4

if you are using the python logging module (and you should be)... here is a way to add the selenium browser logs to the python logging system..

the get_browser_log_entries() function grabs the logs from eth provded driver, emits them to the python logging module as chrome. (ie chrome.console-api, chrome.network etc..) using the timestamp from the browser.(in case there is a delay before you call get_log)

it could probably do with some better exception handling (like if logging is not turned on ) etc.. but it works most of the time..

hop

import logging

from selenium import webdriver

def get_browser_log_entries(driver):
    """get log entreies from selenium and add to python logger before returning"""
    loglevels = { 'NOTSET':0 , 'DEBUG':10 ,'INFO': 20 , 'WARNING':30, 'ERROR':40, 'SEVERE':40, 'CRITICAL':50}

    #initialise a logger
    browserlog = logging.getLogger("chrome")
    #get browser logs
    slurped_logs = driver.get_log('browser')
    for entry in slurped_logs:
        #convert broswer log to python log format
        rec = browserlog.makeRecord("%s.%s"%(browserlog.name,entry['source']),loglevels.get(entry['level']),'.',0,entry['message'],None,None)
        rec.created = entry['timestamp'] /1000 # log using original timestamp.. us -> ms
        try:
            #add browser log to python log
            browserlog.handle(rec)
        except:
            print(entry)
    #and return logs incase you want them
    return slurped_logs

def demo():
    caps = webdriver.DesiredCapabilities.CHROME.copy()
    caps['goog:loggingPrefs'] = { 'browser':'ALL' }
    driver = webdriver.Chrome(desired_capabilities=caps )

    driver.get("http://localhost")

    consolemsgs = get_browser_log_entries(driver)

if __name__ == "__main__":
    logging.basicConfig(level=logging.DEBUG, format='%(asctime)s:%(levelname)7s:%(message)s')
    logging.info("start")
    demo()
    logging.info("end")
ShoeLace
  • 3,476
  • 2
  • 30
  • 44
1

Note that calling driver.get_log('browser') will cause the next call to return nothing until more logs are written to the console.

I would suggest saving the logs to a variable first. For example below logs_2 will equal [].

If you need something in the console to test you can use:

self.driver.execute_script("""

                function myFunction() {
                      console.log("Window loaded")
                }

                if(window.attachEvent) {
            window.attachEvent('onload', myFunction());
        } else {
            if(window.onload) {
                var curronload = window.onload;
                var newonload = function(evt) {
                    curronload(evt);
                    myFunction(evt);
                };
                window.onload = newonload;
            } else {
                window.onload = myFunction();
            }
        }
                """)

logs_1 = driver.get_log('browser')
print("A::", logs_1 )
logs_2 = driver.get_log('browser')
print("B::", logs_2 )
for entry in logs_1:
    print("Aa::",entry)

for entry in logs_2:
    print("Bb::",entry)

See the answer from msridhar for what should go above my example code.

Jortega
  • 3,616
  • 1
  • 18
  • 21