Wait until page is loaded with Selenium WebDriver for Python Wait until page is loaded with Selenium WebDriver for Python selenium selenium

Wait until page is loaded with Selenium WebDriver for Python


The webdriver will wait for a page to load by default via .get() method.

As you may be looking for some specific element as @user227215 said, you should use WebDriverWait to wait for an element located in your page:

from selenium import webdriverfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.common.by import Byfrom selenium.common.exceptions import TimeoutExceptionbrowser = webdriver.Firefox()browser.get("url")delay = 3 # secondstry:    myElem = WebDriverWait(browser, delay).until(EC.presence_of_element_located((By.ID, 'IdOfMyElement')))    print "Page is ready!"except TimeoutException:    print "Loading took too much time!"

I have used it for checking alerts. You can use any other type methods to find the locator.

EDIT 1:

I should mention that the webdriver will wait for a page to load by default. It does not wait for loading inside frames or for ajax requests. It means when you use .get('url'), your browser will wait until the page is completely loaded and then go to the next command in the code. But when you are posting an ajax request, webdriver does not wait and it's your responsibility to wait an appropriate amount of time for the page or a part of page to load; so there is a module named expected_conditions.


Trying to pass find_element_by_id to the constructor for presence_of_element_located (as shown in the accepted answer) caused NoSuchElementException to be raised. I had to use the syntax in fragles' comment:

from selenium import webdriverfrom selenium.common.exceptions import TimeoutExceptionfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.common.by import Bydriver = webdriver.Firefox()driver.get('url')timeout = 5try:    element_present = EC.presence_of_element_located((By.ID, 'element_id'))    WebDriverWait(driver, timeout).until(element_present)except TimeoutException:    print "Timed out waiting for page to load"

This matches the example in the documentation. Here is a link to the documentation for By.


Find below 3 methods:

readyState

Checking page readyState (not reliable):

def page_has_loaded(self):    self.log.info("Checking if {} page is loaded.".format(self.driver.current_url))    page_state = self.driver.execute_script('return document.readyState;')    return page_state == 'complete'

The wait_for helper function is good, but unfortunately click_through_to_new_page is open to the race condition where we manage to execute the script in the old page, before the browser has started processing the click, and page_has_loaded just returns true straight away.

id

Comparing new page ids with the old one:

def page_has_loaded_id(self):    self.log.info("Checking if {} page is loaded.".format(self.driver.current_url))    try:        new_page = browser.find_element_by_tag_name('html')        return new_page.id != old_page.id    except NoSuchElementException:        return False

It's possible that comparing ids is not as effective as waiting for stale reference exceptions.

staleness_of

Using staleness_of method:

@contextlib.contextmanagerdef wait_for_page_load(self, timeout=10):    self.log.debug("Waiting for page to load at {}.".format(self.driver.current_url))    old_page = self.find_element_by_tag_name('html')    yield    WebDriverWait(self, timeout).until(staleness_of(old_page))

For more details, check Harry's blog.