Playwright je framework Microsoftu pro automatizaci prohlížeče: knihovna napsaná hlavně v TypeScriptu s licencí Apache-2.0, která spustí skutečný prohlížeč, ovládá ho přes jedno API a vrátí stránku až ve chvíli, kdy na ní doběhne JavaScript. Často se prezentuje jako nástroj pro end-to-end testování, ale právě jeho jádro si spousta lidí tiše bere ve chvíli, kdy HTTP požadavek vrátí prázdnou schránku tam, kde mají být data. Svou povahou konkuruje Puppeteeru a Selenium — tedy skutečným prohlížečům, které skriptujete, ne HTTP klientům, které jen parsujete.
microsoft/playwright 1.56.0 jsem pustil přes pevně danou sadu scrapingových testů — statický katalog s stránkováním, článek, katalog renderovaný přes JavaScript, JSON API, rozbitou 500, malý crawl graf a dva veřejné procvičovací weby — na Node v22.22.3, macOS arm64, pouze v Chromiu. Renderovací část dopadla bez problémů. Crawlovací část ale v nástroji vůbec neexistuje, a právě to je na Playwrightu před nasazením to nejdůležitější pochopit.
Co mě zaujalo nejvíc
Na špičce výsledků jsou dvě věci, které ukazují trochu jiným směrem.
První je očekávaný výsledek prohlížeče, omezený na moje čekací podmínky. Po page.goto(..., { waitUntil: 'domcontentloaded' }) test s dynamickým fixture čekal na #dynamic-products article.product-card a veřejný test Quotes to Scrape čekal na .quote. Jakmile se tyto selektory specifické pro aplikaci objevily, testy vrátily 8/8 položek z fixture a 10 citátů z veřejného webu; u fixture byl výsledek na osmi položkách přesný na recall 1.0. Nebylo potřeba psát vlastní polling loop, ale Playwright problém s připraveností sám nevyřešil — podmínku dokončení dodal test. Hned napoprvé se také podařilo uložit screenshot celé stránky.
Druhý výsledek využil browserContext.request: konkrétně ctx.request.get(...) poté, co už byl Chromium spuštěný a existoval browser context. Tím se přímo zavolal JSON endpoint fixture a vrátilo se 8/8 produktů, aniž by se vytvářela nebo renderovala stránka. Tím se obejde DOM práce, ne ale cena za běh browser procesu v tomto harnessu. Request klient navázaný na context může sdílet cookies s otevřenými stránkami; samostatné playwright.request.newContext() se obejde bez browser contextu, ale automaticky nesdílí session. Test pokryl jen první variantu.
Playwright také nenabízí crawl queue, zapisovač datasetu ani automatické throttlování. Můj test crawl grafu — projít interní odkazy, hlídat hloubku a nevracet se na už navštívené stránky — došel na 12 stránek ve hloubkách {0:1, 1:4, 2:7}, ale breadth-first traversal byl můj vlastní testovací kód. Playwright otevírá a inspektuje stránky; práce s frontou, politika URL, retry logika a plánování patří do jiné vrstvy.
Co Playwright vlastně je
Nástroj — microsoft/playwright na GitHubu — je napsaný v TypeScriptu, má licenci Apache-2.0 a spravuje ho Microsoft. Testovaná verze byla 1.56.0 ze dne 9. července 2026. Výsledky tedy popisuji pro tuto konkrétní verzi, ne jako obecné tvrzení o kompatibilitě budoucích vydání.
Oficiální zařazení je přesné: jde o framework pro webové testování a automatizaci, který přes jedno API ovládá Chromium, Firefox a WebKit. Hlavní cesta v Playwrightu vede přes test runner s fixtures, assertiony a trace viewerem. Pro scraping jako základní stavební prvek se používá zdokumentovaný režim Library mode: chromium.launch(), pak context, pak page, mimo testovací harness. V celé této recenzi jsem používal právě toto veřejné API. Neprováděl jsem test kompatibility napříč verzemi, takže tohle není tvrzení, že každé otestované chování zůstane stejné v dalších releasech.
Šíře podpory je uváděná jako hlavní přednost jinde, proto ji řeknu přesně. Playwright ovládá tři browser enginy — Chromium, Firefox a WebKit — přes jedno API a nabízí i nativní klienty v Pythonu, Javě a .NET nad JavaScriptem. To je zdokumentované a skutečně jde o jeho největší strukturální výhodu. Co ale tento testovací průchod skutečně pokryl, je užší:
| Schopnost | Stav v této recenzi |
|---|---|
| Chromium engine | Otestováno — všechny testy zde běžely v Chromiu |
| Firefox engine | Zdokumentováno, zde neověřeno |
| WebKit engine | Zdokumentováno, zde neověřeno |
| Jedno API pro všechny tři enginy | Zdokumentováno, zde neověřeno |
| Klienti pro Python, Javu a .NET | Zdokumentováno, zde neověřeno |
| Proxying | Netestováno |
| Škálování více contextů paralelně | Netestováno |
| Interceptování sítě pro API-first scraping | Netestováno |
Pokud se cílový web v Safari/WebKitu vykresluje jinak nebo váš tým píše v Pythonu, právě tato šíře je argumentem pro Playwright — jen z mých výsledků nevyvozujte, že Firefox nebo WebKit mají stejný výsledek, protože jsem je netestoval.
Jak to funguje pod kapotou
Mentální model je browser engine, který skriptujete. chromium.launch() spustí browser proces. context je izolovaná session s vlastními cookies, úložištěm a cache; page je záložka uvnitř tohoto contextu. Zavoláte page.goto(url), počkáte na stav, který odpovídá připravenosti aplikace, a výsledné DOM čtete pomocí helperů jako page.$$eval. Je to mnohem blíž uživatelskému prohlížeči než parsování HTTP odpovědi, ale není to identita prostředí: headless režim, viewport, locale, fonty, stav profilu, TLS/síťová trasa i ochrany webu mohou pořád změnit to, co se vrátí. Tahle recenze netestovala anti-bot chování ani shodu s plnohodnotným produkčním browserem.
page.screenshot() zachytí vyrenderovanou stránku, buď celou, nebo oříznutou, a v mém běhu fungoval hned napoprvé. A API pro requesty, které jsem zmiňoval — context.request.get — používá cookies stejného contextu, ale obejde renderování, takže v jednom skriptu můžete míchat „načti stránku a přečti DOM“ s „jen zavolej JSON endpoint“ bez přepínání nástrojů.
Co pod kapotou není, je crawl machinery. Není tu request scheduler, uložená navštívená množina, politika slušného zatížení ani exportní pipeline. Omezený traversal se sice dá snadno načrtnout, ale spolehlivé crawl frontě už musíte přidat normalizaci URL, práci s přesměrováním, retry, scope pravidla, throttling i obnovu po chybě. Tuto vrstvu si buď napíšete sami, nebo použijete framework, který browser engine obaluje.
Realita instalace a setupu
Instalace má dva kroky a ten druhý nese většinu nákladů na nasazení. npm install playwright nainstaluje knihovnu; samostatné npx playwright install stáhne buildy browserů (v mém případě Chromium). Počítejte s diskovým místem, časem stahování, cachingem browserů v CI a úklidem procesů, neberte npm balíček jako celý běžící systém.
Pokud Playwright nainstalujete s očekáváním scraperu a půjdete podle testovacího tutoriálu, skončíte u testovacích souborů a expect() assertionů. Scraping naopak používá přímo library API. Obě cesty jsou zdokumentované, ale rozdíl je důležitý při hledání příkladů i při volbě deployment příkazů.
V tomto běhu byly užitečné ergonomie velmi konkrétní: browser contexts oddělily stav session, async volání se skládala čistě, screenshot byl otázkou jednoho příkazu a HTTP 500 šlo pořád inspectovat přes response objekt. Slabší stránka byla spíš provozní než syntaktická: browser build bylo nutné nainstalovat a jeho životní cyklus řídit odděleně od knihovny.
Praktické výsledky

Všechna lokální čísla běžela proti fixture serveru na 127.0.0.1 a ground truth byl zapsaný předem před crawl testem. Přesný harness je v run_playwright_material_tests.mjs a přiložené raw artifacts obsahují ground truth i výstupy jednotlivých testů. Jde stále o pozorování z jednoho stroje a jednoho běhu; odkazy slouží k reprodukci, ne ke změně na široký benchmark.
| Test | Cíl | Výsledek |
|---|---|---|
| Statický katalog + stránkování | lokální fixture | 12/12 produktů, recall 1.0 |
| Extrakce článku | lokální fixture | titul + 3/3 odstavce, boilerplate odděleně |
| Dynamická JS stránka (nativní render) | lokální fixture | 8/8, recall 1.0, uložen full-page screenshot |
Dynamické JSON API (page.request) | lokální fixture | 8/8, recall 1.0, bez renderovaného DOM |
| Zpracování HTTP 500 | lokální fixture | status 500 šel inspectovat, navigace nehodila chybu |
| Crawl graf (ručně psané BFS) | lokální fixture | 12 stránek, hloubky {0:1, 1:4, 2:7} |
| Books to Scrape | veřejná demo stránka | 20 produktů |
| Quotes JS (renderované JS) | veřejná demo stránka | 10 citátů, nativně vyrenderováno |
Smyčka pro stránkování explicitně následovala další odkaz; Playwright stránky sám nenašel. Selektor pro článek oddělil navigaci a text patičky od výsledku z těla stránky. U chybové větve navigace vrátila response objekt se stavem 500 místo toho, aby vyhodila výjimku, takže bylo na volajícím, zda bude logovat, retryovat nebo pokračovat dál. Dva veřejné procvičovací cíle vrátily počty uvedené v tabulce.
Je důležité říct jasně jednu hranici: všechno zde běželo na Chromiu, na jednom stroji, jednou. Tabulka schopností odděluje dokumentovanou šíři od skutečně otestovaného chování. Suite jsem znovu nespouštěl na jiné verzi Playwrightu, takže z toho neplyne žádný závěr o kompatibilitě napříč verzemi. Stejně tak neuvádím přesné časy jako benchmark; jediný průchod stopkami na jednom notebooku nestačí pro férové porovnání rychlosti.
Připravenost je součástí kontraktu pro extrakci
Výsledky u dynamických stránek závisely na čekání, které reprezentovalo data, která jsem chtěl získat, ne jen na samotné navigaci v prohlížeči. U lokálního katalogu harness navigoval s waitUntil: 'domcontentloaded' a potom volal waitForSelector('#dynamic-products article.product-card') s timeoutem 15 sekund. Ve veřejném běhu Quotes JS se použil stejný stav navigace a čekalo se na .quote s timeoutem 20 sekund. Extrace proběhla až poté, co se tyto selektory objevily.
Ten rozdíl je důležitý při úpravě skriptu. domcontentloaded říká, že byl zpracován počáteční dokument; neříká, že přišla opožděná API odpověď, že doběhla hydratace, že nekonečný seznam přestal růst nebo že virtualizovaný řádek vstoupil do viewportu. Selektor je užitečný, když stačí přítomnost jednoho odpovídajícího elementu. Pokud ale úplnost závisí na známé odpovědi, počtu položek, stavu aplikace nebo tichém síťovém okně, čekejte raději na tuhle podmínku. Podmínka musí být navázaná na výstupní kontrakt: „existuje aspoň jedna karta“ a „načetly se všechny očekávané stránky“ nejsou stejná tvrzení.

Dočasné limity také patří na stranu volajícího. Test používal konečné timeouty na selektory, ale neřešil retry politiku ani nerozlišoval pomalou stránku od trvale změněného selektoru. Produkční wrapper by měl zaznamenat, která readiness podmínka selhala, uložit dostatek stavu stránky pro diagnostiku a rozhodnout, zda je další pokus o navigaci bezpečný. Playwright vám dává události a DOM; neumí odhadnout, co pro vaši úlohu znamenají „kompletní data“.
Tu hranici by bylo dobré dokumentovat vedle každého extractoru, ne ji nechávat jako implicitní timeout.
Cesta přes API má podobný kontrakt. ctx.request.get dával smysl, protože browser context už existoval a sdílení session mohlo být užitečné. Pokud úloha zjistí, že její datový endpoint funguje bez jakékoli browser session, samostatný request context je jiná architektura s jiným životním cyklem i chováním cookies. Tady jsem tyto dvě cesty neporovnával. Berte „bez renderovaného DOM“ jako změřený fakt a teprve potom samostatně rozhodněte, zda je pro širší workflow browser proces potřeba.
Otázka crawlování
Výsledek crawl grafu je ten, který rozhoduje, jak máte o Playwrightu přemýšlet. Dvanáct stránek, tři úrovně, správně — a veškerá logika procházení byla moje. Playwright dodal polovinu „otevři tuto URL a přečti ji“; já jsem dodal frontu, visited set a sledování hloubky.
Pro malé, vymezené úlohy to nevadí. U crawl práce ve větším měřítku to znamená, že buď píšete crawler nad browser knihovnou, nebo Playwright kombinujete s něčím, co crawl vrstvu už obsahuje. Zdokumentovaný vzor je Crawlee, které Playwright (a Puppeteer) obaluje skutečnou request queue, ukládáním datasetů a automatickým throttlingem — zachováte si renderování z Playwrightu a půjčíte si orchestrace. Pokud chcete frontu přímo ve frameworku a ne dodatečně přilepenou, to je celé jádro návrhu Scrapyho, i když Scrapy je primárně HTTP-first a JavaScript sám nenerenderuje. Nejde o to, že by Playwright selhával; jde o to, že „automatizace prohlížeče“ a „crawlování“ jsou dvě různé práce a Playwright si nárokuje jen jednu z nich.

Těch dvanáct stránek v BFS pěkně ukazuje hranici odpovědnosti. Dodal jsem frontu, visited set a sledování hloubky pro řízený graf. Produkční fronta ale stále musí řešit canonicalizaci URL, přesměrování, povolené hosty, duplicitní klíče, retry, konkurenci, delay na hostitele, persistenci i restartovací semantiku. Export je další rozhodnutí: fixture zapisovala JSON a CSV jen proto, že to dělal harness, ne proto, že by Playwright měl dataset abstrakci.
Design session také ovlivňuje wrapper. Jeden browser může obsahovat více contextů s izolovanými cookies a úložištěm, ale v této recenzi jsem neměřil škálování více contextů ani izolaci při chybě. Znovupoužití contextu může zachovat přihlášení a snížit režijní náklady; vytváření oddělených contextů může zabránit úniku stavu mezi úlohami. To jsou crawler-level politiky, i když Playwright poskytuje primitivum contextu. Zvolený životní cyklus benchmarkujte na skutečném browser buildu a v reálném nasazovacím prostředí.
Plusy a mínusy
Plusy:
- JavaScript se vykonává ve skutečném Chromium enginu; oba dynamické cíle se dostaly k selektorům použitým jako readiness podmínky.
- Full-page screenshot se podařilo zachytit hned napoprvé.
- Selektory vytáhly očekávaná data ze statického katalogu i článku v řízených fixture.
browserContext.requestse dostal na JSON endpoint bez renderování stránky, zatímco už spuštěný browser proces zůstal součástí harnessu.- Spolehlivé i při chybové odpovědi: HTTP 500 šlo inspectovat a navigace nevyhodila chybu.
- Zdokumentovaná podpora tří enginů (Chromium, Firefox, WebKit) přes jedno API, plus klienti pro Python, Javu a .NET (zdokumentováno; zde otestováno jen Chromium).
- Apache-2.0 a spravované Microsoftem.
- Velmi čistý vývojářský zážitek, jakmile jste v library mode: jedno API napříč enginy, nativní async, jednoduché screenshoty.
Mínusy:
- Žádná vestavěná crawl queue, dataset ani auto-throttle — crawl práce ve větším měřítku je váš kód nebo wrapper jako Crawlee.
- Váha browseru: stažení binárky a režie na stránku jsou skutečná daň oproti čistě HTTP nástroji.
- Výchozí rámování je test runner; pro scraping musíte vědět, že library mode existuje, a sejít z marketingové cesty.
- Otestovaná byla jen verze Playwright 1.56.0 a Chromium; kompatibilita napříč verzemi i enginy nebyla ověřena.
- Bez vlastního výstupu ve strukturovaném JSON podle schématu; selektory i tvar dat si definujete sami.
Pro koho je vhodný a kdo by se mu měl vyhnout
Pokud je váš problém renderování stránek, kde se data objeví až po doběhnutí JavaScriptu, nebo pokud chcete spolu s DOM daty sbírat i screenshoty, Playwright je rozumný kandidát k otestování na vašich cílech. Týmy, které už Playwright používají na testy, mohou stejné koncepty i práci se selektory znovu použít v library mode. Klienti pro Python, Javu a .NET jsou zdokumentované možnosti, ale tahle recenze testovala jen Node a Chromium.
Ve třech případech zvažte jinou vrstvu. Pokud jsou potřebná data už přítomná v HTTP odpovědi, nástroj postavený na HTTP-first vynechá start browseru i renderovací režii; Colly je v této kategorii crawler knihovna, zatímco Trafilatura míří na extrakci článků. Pokud potřebujete frontování, persistenci a throttling, použijte crawler framework nebo wrapper kolem Playwrightu. A pokud chcete výstup ve tvaru schématu bez údržby selektorů, porovnejte managed extraction služby. Žádnou z těchto alternativ jsem v této recenzi nebenchmarkoval.
Pokud se rozhodujete konkrétně mezi Playwrightem a Puppeteerem, je to samostatný head-to-head; naše srovnání vedle sebe testuje oba na stejných fixture a ukazuje, kde se volba skutečně láme.
Alternativy a místo managed extraction
Playwright je zdarma, s licencí Apache-2.0 a self-hosted. Neseš odpovědnost za nasazení browserů, selektory, readiness podmínky, crawl kód, aktualizace i řešení chyb. Tahle recenze neměřila anti-bot výkon ani neporovnávala celkové provozní náklady s managed službou.
V open source je užitečné srovnávat podle úkolu. Pro crawl ve větším měřítku nad browserem přidává Crawlee frontu a dataset, které Playwright postrádá. Pokud je tvým cílem spíš LLM-ready Markdown ze skutečného browseru než ručně tvarované řádky, Crawl4AI spustí browser a pro tenhle pipeline vrací Markdown. A pokud zvažuješ víc těchto nástrojů najednou, náš přehled open-source scraperů staví kategorie vedle sebe.
Upozornění: Thunderbit je produkt vydavatele a v této Playwright fixture nebyl spuštěn. Reprezentuje kategorii managed extraction: služba se stará o renderování a vrací text stránky nebo záznamy ve tvaru schématu, zatímco u Playwrightu zůstává provoz browseru i logika selektorů na vývojáři. Srovnání je tedy o modelu hostování, podobě výstupu a cenovém modelu — ne o výkonovém výsledku z téhle recenze.
Vyzkoušejte Thunderbit pro extrakci webových dat
Verdikt
Playwright použij tehdy, když tvůj cíl vyžaduje browser engine a ty jsi připravený vlastnit readiness podmínky, selektory i orchestrace crawlů. Tabulka výsledků ukazuje, že jeho Chromium library mode zvládl v tomto autorem provedeném běhu řízené fixture pro statický obsah, dynamický obsah, API, screenshoty i chybové stavy přesně podle očekávání.
Drž hranici důkazů: testovalo se jen Chromium a Node, dvanáctistránkový průchod stál na ručně napsaném BFS, browserContext.request přeskočil render stránky, ale ne už běžící browser proces, a každá dynamická extrakce používala výslovně uvedený readiness selektor. Díky těmto omezením je Playwright v téhle recenzi spíš browser primitivum než změřený end-to-end crawling systém.
Vyzkoušejte Thunderbit pro extrakci webových dat Get Started Free
Časté dotazy
Potřebuji při scrapování s Playwrightem pořád čekání?
Ano. Samotné spuštění prohlížeče tvému skriptu neřekne, kdy jsou data v aplikaci připravená. Tyto testy šly na domcontentloaded a pak čekaly na selektor specifický pro daný cíl, teprve potom se extrahovalo. Produkční stránky mohou potřebovat jiný signál, třeba response, stav locatoru nebo event aplikace.
Umí Playwright sám crawlout celý web? Ne přímo z krabice. Není tu vestavěná request queue, zapisovač datasetu ani auto-throttle — můj crawl graf došel na 12 stránek ve hloubkách {0:1, 1:4, 2:7} jen proto, že jsem breadth-first search napsal ručně. Pro crawl ve větším měřítku je lepší spojit Playwright s Crawlee, které přidá skutečnou crawl vrstvu, nebo použít rovnou crawler framework.
Kdy použít browserContext.request a kdy samostatný request context?
browserContext.request použij, když se HTTP volání mají dělit o cookies s page v existujícím browser contextu. playwright.request.newContext() použij tehdy, když chceš API-only context bez spouštění browseru a nepotřebuješ automatické sdílení cookies s browser stránkami. Tady byla testovaná jen první cesta.
Byly tu testované Firefox a WebKit? Ne. Všechny testy běžely v Chromiu, na jednom stroji, jen jednou. Podpora tří enginů v Playwrightu (Chromium, Firefox, WebKit) i klienti pro Python, Javu a .NET jsou zdokumentované schopnosti, které zde uvádím jako deklarované, ne ověřené — parita Firefoxu a WebKitu, proxying, paralelní škálování i network interception jsou mimo rozsah těchto čísel.
Jaké prostředí tato recenze pokrývala? Playwright 1.56.0, Node v22.22.3, macOS arm64 a pouze Chromium. Firefox, WebKit, proxying, paralelní škálování, anti-bot chování a novější verze Playwrightu byly mimo tento běh. Instalace vyžadovala knihovnu a k tomu samostatné stažení browser buildů.


