Developer Snippet Diary

Patchright Tutorial installation + basic code async, sync

Patchright provides a stealth-focused (websites cannot easily detect that a bot (like Playwright/Selenium)) browser automation solution that maintains full API compatibility with Playwright.

Use: web scraping of protected sites, automated testing against security systems, and browser automation tasks where avoiding detection is critical.

simply change `from playwright.sync_api` to `from patchright.sync_api` (or the async equivalent). 

1. Create virtual Enviorment (optional)

pip install virtualenv
virtualenv venv
venv\Scripts\activate

2. install patchright

pip install patchright

3. install browser

patchright install chrome
#or
patchright install chromium

4. make file abc.py SYNC

from patchright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(
        channel="chrome",
        headless=False
    )

    page = browser.new_page()
    page.goto("https://example.com")

    print(page.title())

    browser.close()

OR ASYNC

import asyncio
import os
from patchright.async_api import async_playwright

async def main():
    async with async_playwright() as p:
        # Define where to store browser data (cookies, cache, etc.)
        user_data_dir = os.path.join(os.getcwd(), "chrome_profile")
        
        # Best Practice: Launching a persistent context with Chrome
        # This bypasses standard fingerprinting by using a real browser channel
        context = await p.chromium.launch_persistent_context(
            user_data_dir=user_data_dir,
            channel="chrome",  # Uses the actual Chrome browser installed on your system
            headless=False,    # Headful is generally harder to detect
            no_viewport=True,  # Allows the window to dictate size, preventing scaling mismatches
            # Avoid adding custom user_agent or extra_headers here to maintain a clean fingerprint
        )

        # In a persistent context, a page is usually opened automatically
        page = context.pages[0] if context.pages else await context.new_page()

        # Navigate and perform actions
        await page.goto('https://playwright.dev')
        print(f"Title: {await page.title()}")
        
        # Take the screenshot
        await page.screenshot(path=f'example-chrome-stealth.png')

        # Close the context properly
        await context.close()

if __name__ == "__main__":
    asyncio.run(main())

 

with async:
1. open multiple pages

import asyncio
import os
from patchright.async_api import async_playwright

urls = [
    "https://example.com",
    "https://example.org",
    "https://example.net"
]

async def open_page(context, url):
    page = await context.new_page()
    await page.goto(url)
    print(f"{url} → {await page.title()}")

async def main():
    async with async_playwright() as p:
        user_data_dir = os.path.join(os.getcwd(), "chrome_profile")
        context = await p.chromium.launch_persistent_context(
            user_data_dir=user_data_dir,
            channel="chrome",
            headless=False,
            no_viewport=True,
        )
        # ???? PARALLEL execution, * unpack list, gather accept list
        await asyncio.gather(*[
            open_page(context, url) for url in urls
        ])
        await context.close()
asyncio.run(main())

2. auto google search

import asyncio
import os
from patchright.async_api import async_playwright

async def main():
    async with async_playwright() as p:
        user_data_dir = os.path.join(os.getcwd(), "chrome_profile")
        context = await p.chromium.launch_persistent_context(
            user_data_dir=user_data_dir,
            channel="chrome",  # Uses the actual Chrome browser installed on your system
            headless=False,    # Headful is generally harder to detect
            no_viewport=True,  # Allows the window to dictate size, preventing scaling mismatches
        )
        page = context.pages[0] if context.pages else await context.new_page()

        await page.goto("https://www.google.com")

        await page.wait_for_timeout(2000)
        await page.fill("textarea[name='q']", "Patchright tutorial")

        await page.wait_for_timeout(1000)
        await page.keyboard.press("Enter")

        await page.wait_for_timeout(3000)
        print("Searched:", "Patchright tutorial"-)

if __name__ == "__main__":
    asyncio.run(main())

3. login attempt

import asyncio
import os
from patchright.async_api import async_playwright

async def login(page):
    await page.goto("https://practicetestautomation.com/practice-test-login/")

    await page.fill("#username", "student")
    await page.fill("#password", "Password123")

    await page.click("#submit")
    await page.wait_for_timeout(3000)

    print("Login attempted")

async def main():
    async with async_playwright() as p:
        user_data_dir = os.path.join(os.getcwd(), "chrome_profile")
        context = await p.chromium.launch_persistent_context(
            user_data_dir=user_data_dir,
            channel="chrome",  # Uses the actual Chrome browser installed on your system
            headless=False,    # Headful is generally harder to detect
            no_viewport=True,  # Allows the window to dictate size, preventing scaling mismatches
        )
        page = context.pages[0] if context.pages else await context.new_page()
        await login(page)

if __name__ == "__main__":
    asyncio.run(main())


4. data scraping 

import asyncio
import os
from patchright.async_api import async_playwright

async def scrape_titles(page):
    await page.goto("https://news.ycombinator.com")

    titles = await page.locator(".titleline > a").evaluate_all(
        "els => els.map(el => el.textContent)"
    )

    for t in titles:
        print("Title:", t)

async def main():
    async with async_playwright() as p:
        user_data_dir = os.path.join(os.getcwd(), "chrome_profile")
        context = await p.chromium.launch_persistent_context(
            user_data_dir=user_data_dir,
            channel="chrome",  # Uses the actual Chrome browser installed on your system
            headless=False,    # Headful is generally harder to detect
            no_viewport=True,  # Allows the window to dictate size, preventing scaling mismatches
        )
        page = context.pages[0] if context.pages else await context.new_page()
        await scrape_titles(page)

if __name__ == "__main__":
    asyncio.run(main())


Posted by: R GONDAL
Email: rizikmw@gmail.com