Search code examples
pythonplaywright

Saving Login with Playwright


I'm trying to save my login with playwright, I've read the documentation and tried to implement it into my code but I am still getting errors

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=False, slow_mo=50)
    page = context.new_page()
    page.fill("input#input-username", "demo")
    page.fill("input#input-password", "demo")
    page.click("button[type=submit]")
    context = browser.new_context(storage_state="website1.json")
    storage = context.storage_state(path="website1.json")
page = context.new_page()

NameError: name 'context' is not defined

Super confused.


Solution

  • The main problem:

    context.new_page() calls before variable declaration(context = ...)

    Should works fine:

    from playwright.sync_api import sync_playwright
    
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False, slow_mo=50)
        context = browser.new_context(storage_state="website1.json")
        page = context.new_page()
        page.goto('https://demo.opencart.com/admin')
        page.fill("input#input-username", "demo")
        page.fill("input#input-password", "demo")
        page.click("button[type=submit]")
    

    Also you can use Persistent authentication:

    from playwright.sync_api import sync_playwright
    
    with sync_playwright() as p:
        user_data_dir = 'FULL_PATH_TO_BROWSER_PROFILE'
        browser = p.chromium.launch_persistent_context(user_data_dir, headless=False)
        # login only 1 time...
    

    JFYI: opencart uses user_token in GET parameters and validates it. playwright(storage_state, user_data_dir etc) should works fine. Example:

    # run docker container with playwright
    docker rm -fv example && docker run --name example -it mcr.microsoft.com/playwright/python:v1.27.1-focal bash
    # create empty state
    echo {} >> /tmp/state.json
    # run python in interactive mode
    python
    # Python 3.8.10 (default, Jun 22 2022, 20:18:18) 
    # [GCC 9.4.0] on linux
    # Type "help", "copyright", "credits" or "license" for more information.
    

    Paste the next script:

    from time import sleep
    from urllib.parse import parse_qs
    
    from playwright.sync_api import sync_playwright
    
    with sync_playwright() as p:
        # login
        browser = p.chromium.launch()
        context = browser.new_context(storage_state='/tmp/state.json')
        page = context.new_page()
        page.goto('https://demo.opencart.com/admin')
        page.fill('input#input-username', 'demo')
        page.fill('input#input-password', 'demo')
        page.click('button[type=submit]')
        sleep(5)  # just wait for redirect - you can wait for a element...
        page.context.storage_state(path='/tmp/state.json')
        page.screenshot(path='/tmp/after_state_init.png')
        # parse user_token for GET requests
        parsed_url = parse_qs(page.url)
        user_token = parsed_url['user_token'][0]
        print(f'user token {user_token}')
        page.close()
        browser.close()
    
    
    with sync_playwright() as p:
        # open admin dashboard without login... 
        browser = p.chromium.launch()
        context = browser.new_context()
        page = browser.new_page(storage_state='/tmp/state.json')
        page.goto(f'https://demo.opencart.com/admin/index.php?route=common/dashboard&user_token={user_token}')
        sleep(5)
        page.screenshot(path='/tmp/open_using_saved_state.png')
        page.close()
        browser.close()
    

    Now open a new terminal and copy screens from docker container:

    docker cp example:/tmp/after_state_init.png ./
    docker cp example:/tmp/open_using_saved_state.png ./
    

    You'll see that they are the same - admin dashboard works without login.