DataLens

Setting up Playwright and launching a browser

Install Playwright with uv, launch a browser from Python, and understand the three objects every script uses (browser, context, page) and how to close them cleanly.

Level: Foundations · 7 min read

Practise this module

The questions for this lesson run in your browser and check your answer straight away.

The idea

Every Playwright script, from a 5-line test to a scraper that runs every night, starts the same way: start Playwright, launch a browser, open a page. This module covers that skeleton properly, so the rest of the track can focus on the interesting parts.

Installing (on your own computer)

Playwright is two things: a Python package, and the browsers it controls. In a uv project:

uv add playwright
uv run playwright install chromium

The first command adds the package to pyproject.toml; the second downloads a matching Chromium build (about 150 MB, once). In this course, a practice browser is already set up, so the code below runs right here.

The skeleton

Every Playwright script starts the same way: launch a browser, open a tab, go to a page, do your work, and close up. Here's the smallest version, which visits the practice shop and prints the page title:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()
    page.goto("https://nusantara-gadget.test/")
    print(page.title())
    browser.close()
Nusantara Gadget — Official Gadget Store

Line by line:

The sync in sync_playwright means each line waits for its action to finish before moving on, which is exactly what you want for scripts. Playwright also has an async_api for running many pages concurrently; you won't need it until you're scraping at scale.

Headless or headed?

By default the browser is headless: it runs without a visible window. That's faster and what you want on servers. While developing, it's often useful to see what's happening:

with sync_playwright() as p:
    browser = p.chromium.launch(headless=False, slow_mo=500)
    page = browser.new_page()
    page.goto("https://nusantara-gadget.test/products")
    print(page.title())
    browser.close()
Products — page 1 — Nusantara Gadget

headless=False opens a real window; slow_mo=500 pauses 500 ms between actions so you can follow along. Switch back to headless once the script works.

Browser, context, page

Playwright has three levels:

ObjectIs likeHolds
Browserthe browser applicationone or more contexts
BrowserContexta fresh, private browser profilecookies, storage, settings (viewport, user agent)
Pagea tabone URL at a time

browser.new_page() is a shortcut that creates a context with one page. Create contexts yourself when you need settings, or several independent sessions:

with sync_playwright() as p:
    browser = p.chromium.launch()
    phone = browser.new_context(viewport={"width": 390, "height": 844})
    laptop = browser.new_context(viewport={"width": 1440, "height": 900})
    phone_page = phone.new_page()
    laptop_page = laptop.new_page()
    phone_page.goto("https://nusantara-gadget.test/deals")
    laptop_page.goto("https://nusantara-gadget.test/products")
    print(phone_page.viewport_size, phone_page.title())
    print(laptop_page.viewport_size, laptop_page.title())
    browser.close()
{'width': 390, 'height': 844} Flash deals — Nusantara Gadget
{'width': 1440, 'height': 900} Products — page 1 — Nusantara Gadget

Contexts are cheap and isolated: logging in on one doesn't log in the other. That's how you'd scrape as two different users, or start each run with a clean slate.

Key idea

sync_playwright() → launch() a browser → new_context() for a clean profile → new_page() for a tab → goto(url). Always close the browser, and let the with block clean up Playwright.

Outside a with block

In a notebook or an interactive session you may want the browser to stay open between cells. Use start() and stop() instead of with:

p = sync_playwright().start()
browser = p.chromium.launch()
page = browser.new_page()
page.goto("https://nusantara-gadget.test/catalog")
print(page.url)
browser.close()
p.stop()
https://nusantara-gadget.test/catalog

You're now responsible for calling close() and stop() yourself; in scripts, prefer the with form.

Why this matters for clean code

Resource cleanup is the difference between a script that runs for months and one that slowly fills a server with zombie browser processes. Context managers (with) make cleanup automatic, and wrapping the skeleton in a function (as in the exercises) means you write it once and every scraper reuses it.

Recap

Practise this module

The questions for this lesson run in your browser and check your answer straight away.

Next: Navigating pages and taking screenshots →