25

Is there a way that for different runs of a python program that uses selenium I keep the browser that I have opened and logged in with my credentials, open and use in later runs?

I am debugging a code. On the browser each time I need to log in using my credentials. Currently, everytime I stop the code, the web-browser gets closed. Is there a way to keep a copy of browser that I have already open and logged in open and use it for my later debug so every time I don't need to enter my login credentials again?

My code that opens the browser looks like this:

driver = webdriver.Chrome(executable_path="/the_path/chromedriver", chrome_options=chrome_options) 
driver.get(url)

EDIT:

Actually, the way this website asks for authentication is as follows: First, it asks for the username, then I need to press the continue button, then it asks for the password, after entering the password, it sends an SMS to my phone, I need to enter it before it goes to the intended page.

0m3r
  • 12,286
  • 15
  • 35
  • 71
TJ1
  • 7,578
  • 19
  • 76
  • 119
  • Possible duplicate of [Python: use cookie to login with Selenium](https://stackoverflow.com/questions/45417335/python-use-cookie-to-login-with-selenium) – Arount Feb 20 '18 at 08:27
  • Possible duplicate of [How can I reconnect to the browser opened by webdriver with selenium?](https://stackoverflow.com/questions/47861813/how-can-i-reconnect-to-the-browser-opened-by-webdriver-with-selenium) – undetected Selenium Feb 20 '18 at 09:14
  • I don't think this is a duplicate of any of those, please see my EDIT part of the question. – TJ1 Feb 20 '18 at 15:19
  • you are asking 2 unrelated questions: "how do I re-use existing browser" and "how do I automate multi-factor auth" – Corey Goldberg Feb 20 '18 at 18:50

5 Answers5

22

Well, since this question is upvoted but my flag as duplicated question wasn't accepted I will post here the same exact answer I already posted for a similar question:


You can use pickle to save cookies as text file and load it after:

def save_cookie(driver, path):
    with open(path, 'wb') as filehandler:
        pickle.dump(driver.get_cookies(), filehandler)

def load_cookie(driver, path):
     with open(path, 'rb') as cookiesfile:
         cookies = pickle.load(cookiesfile)
         for cookie in cookies:
             driver.add_cookie(cookie)

With a script like:

from selenium import webdriver
from afile import save_cookie

driver = webdriver.Chrome()
driver.get('http://website.internets')

foo = input()

save_cookie(driver, '/tmp/cookie')

What you can do is:

  1. Run this script
  2. On the (selenium's) browser, go to the website, login
  3. Go back to your terminal, type anything hit enter.
  4. Enjoy your cookie file at /tmp/cookie. You can now copy it into your code repo and package it into your app if needed.

So, now, in your main app code:

from afile import load_cookie

driver = webdriver.Chrome()
load_cookie(driver, 'path/to/cookie')

And you are now logged.

Arount
  • 9,853
  • 1
  • 30
  • 43
  • Thanks for the answer. Would this work for the multi-factor authentication that I explained in my updated question (please see the EDIT part)? – TJ1 Feb 20 '18 at 15:17
  • Theoretically if your browser auto-log you when you browse the website by hand, it will works the same with the cookies method. Obviously you will have to login manually first, but this only one time – Arount Feb 20 '18 at 15:19
  • I could not find any library called `afile`, can you elaborate what it is? – TJ1 Feb 20 '18 at 15:25
  • it's only an example. `afile` is a Python module. In brief: A file named `afile.py` containing both functions `save_cookie` and `load_cookie`. [this article](https://learn.adafruit.com/micropython-basics-loading-modules/import-code) gives you an example of module usage (in the article the guy use `test` where I use `afile`). – Arount Feb 20 '18 at 15:53
  • Oh, I see got it thanks. Will try this later and report back the results. – TJ1 Feb 20 '18 at 15:55
  • I tried your solution. First of all, I needed to add something like `driver.get("https://www.google.com/")` before `load_cookie` so the code does not crash, according to https://stackoverflow.com/questions/47393292/unable-to-add-a-cookie-using-selenium-splinter, and even after that, the answer does not do anything. – TJ1 Feb 22 '18 at 15:18
6

This was a feature request and closed as not feasible. But is a way to do it, use folders as profiles and keep all logins persistent from session to session by using the Chrome options user-data-dir in order to use folders as profiles, I run:

chrome_options = Options()
chrome_options.add_argument("user-data-dir=selenium") 
driver = webdriver.Chrome(chrome_options=chrome_options)
driver.get("www.google.com")

You can manually interact at this step with the opened window and do the logins that check for human interaction, check remember password etc I do this and then the logins, cookies I need now every-time I start the Webdriver with that folder everything is in there. You can also manually install the Extensions and have them in every session. Second time I run, with exactly the same code as above, all the settings, cookies and logins are there:

chrome_options = Options()
chrome_options.add_argument("user-data-dir=selenium") 
driver = webdriver.Chrome(chrome_options=chrome_options)
driver.get("www.google.com") #Now you can see  the cookies, the settings, Extensions and the logins done in the previous session are present here

The advantage is you can use multiple folders with different settings and cookies, Extensions without the need to load, unload cookies, install and uninstall Extensions, change settings, change logins via code, and thus no way to have the logic of the program break, etc Also this is faster than having to do it all by code.

Eduard Florinescu
  • 16,747
  • 28
  • 113
  • 179
  • Thanks for the answer. I tried it, however, it doesn't resolve the problem. Actually, when I open the browser it 1st asks for email address then I need to click on continue, then it asks for the password, then when I click on ok, it sends an SMS with a code to my phone, that I need to enter. Then it goes to the intended page. Your solution just bypassed asking for email, but asking for the password and text messages are still remaining. – TJ1 Feb 20 '18 at 15:01
  • @TJ1 That's a tough security check if it ask for so many checks every session, I think is rather the exception than the rule – Eduard Florinescu Feb 20 '18 at 20:22
2

I had a exact same scenario where I would like to reuse once authenticated/logged-in sessions. I'm using multiple browser simultaneously.

I've tried plenty of solutions from blogs and StackOverflow answers.

1. Using user-data-dir and profile-directory

These chrome options which solves purpose if you opening one browser at a time, but if you open multiple windows it'll throw an error saying user data directory is already in use.

2. Using cookies

Cookies can be shared across multiple browsers. Code available in SO answers are have most of the important blocks on how to use cookies in selenium. Here I'm extending those solutions to complete the flow.

Code

# selenium-driver.py
import pickle
from selenium import webdriver


class SeleniumDriver(object):
    def __init__(
        self,
        # chromedriver path
        driver_path='/Users/username/work/chrome/chromedriver',
        # pickle file path to store cookies
        cookies_file_path='/Users/username/work/chrome/cookies.pkl',
        # list of websites to reuse cookies with
        cookies_websites=["https://facebook.com"]

    ):
        self.driver_path = driver_path
        self.cookies_file_path = cookies_file_path
        self.cookies_websites = cookies_websites
        chrome_options = webdriver.ChromeOptions()
        self.driver = webdriver.Chrome(
            executable_path=self.driver_path,
            options=chrome_options
        )
        try:
            # load cookies for given websites
            cookies = pickle.load(open(self.cookies_file_path, "rb"))
            for website in self.cookies_websites:
                self.driver.get(website)
                for cookie in cookies:
                    self.driver.add_cookie(cookie)
                self.driver.refresh()
        except Exception as e:
            # it'll fail for the first time, when cookie file is not present
            print(str(e))
            print("Error loading cookies")

    def save_cookies(self):
        # save cookies
        cookies = self.driver.get_cookies()
        pickle.dump(cookies, open(self.cookies_file_path, "wb"))

    def close_all(self):
        # close all open tabs
        if len(self.driver.window_handles) < 1:
            return
        for window_handle in self.driver.window_handles[:]:
            self.driver.switch_to.window(window_handle)
            self.driver.close()

    def __del__(self):
        self.save_cookies()
        self.close_all()


def is_fb_logged_in():
    driver.get("https://facebook.com")
    if 'Facebook – log in or sign up' in driver.title:
        return False
    else:
        return True


def fb_login(username, password):
    username_box = driver.find_element_by_id('email')
    username_box.send_keys(username)

    password_box = driver.find_element_by_id('pass')
    password_box.send_keys(password)

    login_box = driver.find_element_by_id('loginbutton')
    login_box.click()


if __name__ == '__main__':
    """
    Run  - 1
    First time authentication and save cookies

    Run  - 2
    Reuse cookies and use logged-in session
    """
    selenium_object = SeleniumDriver()
    driver = selenium_object.driver
    username = "fb-username"
    password = "fb-password"

    if is_fb_logged_in(driver):
        print("Already logged in")
    else:
        print("Not logged in. Login")
        fb_login(username, password)

    del selenium_object

Run 1: Login & Save Cookies

$ python selenium-driver.py
[Errno 2] No such file or directory: '/Users/username/work/chrome/cookies.pkl'
Error loading cookies
Not logged in. Login

This will open facebook login window and enter username-password to login. Once logged-in it'll close the browser and save cookies.

Run 2: Reuse cookies to continue loggedin session

$ python selenium-driver.py
Already logged in

This will open logged in session of facebook using stored cookies.

Hardik Sondagar
  • 4,347
  • 3
  • 28
  • 48
1

I got a solution for you. Just follow the mentioned step.

Outcome: You can run the script on the already opened window without restarting the browser.

step 1: we have to set an environment variable of chrome application. To do this go to the directory where the chrome application is located. Copy the path and past it to the environment variable. step 2: make a directory where you will store the remote debugging chrome window. like "D:\Selenium\Chrome_Test_Profile". step 3: open CMD and write the command

chrome.exe -remote-debugging-port=9014 --user-data dir="D:\Selenium\Chrome_Test_Profile"

step 4: use following code

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
from selenium.webdriver.chrome.options import Options


path = r"C:\Program Files (x86)\chromedriver.exe"
chrome_options = Options()
chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9014")
#Change chrome driver path accordingly
chrome_driver = path
driver = webdriver.Chrome(chrome_driver, chrome_options=chrome_options)
print (driver.current_url)

And you are done.

0

Saving the cookies with pickle works. For me I also needed to do driver.refresh() after clicking the final button otherwise the browser froze.

Jeffrey Kozik
  • 201
  • 4
  • 8