Tôi đã chạy Playwright và Puppeteer qua cùng một bộ kiểm thử scraping

Cập nhật lần cuối vào July 17, 2026
Tôi đã chạy Playwright và Puppeteer qua cùng một bộ kiểm thử scraping
Tóm tắt bằng AI
Bài so sánh này chạy Playwright và Puppeteer trên cùng một bộ fixture scraping để kiểm tra liệu một trong hai thư viện tự động hóa trình duyệt có vượt trội rõ ràng hay không. Kết quả hầu như hòa trên các trang tĩnh, trang render bằng JavaScript, ảnh chụp màn hình, trích xuất dựa trên JSON, xử lý lỗi và một đồ thị crawl viết tay. Bài viết sau đó giải thích các yếu tố quyết định thực sự: phạm vi engine trình duyệt, hỗ trợ ngôn ngữ, mức độ phù hợp với hệ sinh thái, và việc không công cụ nào là crawler hoàn chỉnh ngay từ đầu. Bài cũng gợi ý Crawlee cùng các bài đánh giá công cụ đơn lẻ khác khi bạn cần orchestration, scraping thiên về HTTP, hoặc giải pháp trích xuất được quản lý thay vì chỉ điều khiển trình duyệt thô.

Hầu hết các bài viết kiểu "Playwright vs Puppeteer" đều khởi đầu từ giả định rằng một trong hai phải là công cụ scrape tốt hơn. Nhưng cách đặt vấn đề như vậy đã vô tình kéo theo khá nhiều điều chưa chắc đã đúng. Tôi đã đưa cả hai thư viện vào cùng một bộ trang kiểm thử — một danh mục tĩnh, một danh mục render bằng JavaScript, một bài viết, một trang lỗi 500, một đồ thị crawl nhỏ, và hai site thực hành công khai — và kết quả gần như không thể phân biệt. Cùng độ bao phủ, cùng cách render, cùng ảnh chụp màn hình, cùng những chỗ bị thiếu.

Vì vậy, đây không phải là một màn đăng quang. Trong những tác vụ thực sự quyết định liệu một công cụ tự động hóa trình duyệt có scrape được trang hay không, không bên nào bật lên rõ rệt. Phần dưới đây sẽ chỉ ra khác biệt thực sự duy nhất có thể ảnh hưởng đến lựa chọn của bạn, điều mà cả hai đều âm thầm để bạn tự xây dựng, cùng một lưu ý về khoảng cách phiên bản mà tôi đã kiểm tra (tính đến 2026-07-09).

Vì sao phép so sánh này là công bằng

Các bài so sánh thường có thói quen test mỗi công cụ trên những trang khác nhau rồi công bố bên thắng cuộc — điều đó nói nhiều hơn về trang test hơn là về công cụ. Tôi tránh điều đó bằng cách chạy Playwright và Puppeteer trên cùng một máy chủ fixture nội bộ và cùng các demo công khai, Books to ScrapeQuotes to Scrape, để mọi con số đều có thể đối chiếu từng cột với nhau.

Chỉ khi đó, một tuyên bố "hòa" mới có ý nghĩa. Nếu fixture khác nhau, kết quả hòa chỉ là nhiễu. Khi chúng giống hệt nhau đến từng byte, kết quả khớp nhau mới là tín hiệu nói lên bản thân công cụ.

Mỗi công cụ thực chất là gì

Puppeteer là một API JavaScript để điều khiển Chrome, thông qua Chrome DevTools Protocol. Cách mô tả chính thức của nó cũng đúng như vậy: "một API JavaScript để điều khiển Chrome (và thử nghiệm Firefox)." Nó trưởng thành, tập trung vào Chrome và chạy trên Node.

Playwright được mô tả theo hướng khác — "một framework cho kiểm thử và tự động hóa web" có thể điều khiển Chromium, Firefox và WebKit qua một API duy nhất, với client chính thức bằng JavaScript, Python, Java và .NET. Hai công cụ này có chung nguồn gốc (Playwright xuất phát từ nhóm đứng sau Puppeteer ở Google trước khi chuyển sang Microsoft), nên chúng giống anh em họ hơn là đối thủ.

Tuy nhiên, với mục đích scraping, chúng hoạt động theo cùng một cách. Khởi chạy một trình duyệt thật, mở trang, để script chạy xong, rồi đọc DOM đã render. Đó chính là lý do bạn chọn một trong hai thay vì một bộ phân tích HTTP: bạn cần trang sau khi JavaScript thực thi, chứ không phải bộ khung rỗng trước đó. Mọi thứ bên dưới đều bắt nguồn từ cơ chế chung này — và đó cũng là lý do rất nhiều khác biệt giữa chúng cuối cùng lại hóa ra ngang nhau.

Kết quả, đặt cạnh nhau

Playwright vs Puppeteer identical results matrix

Đây là lúc câu chuyện "một bên rõ ràng tốt hơn" lặng lẽ sụp đổ. Cùng fixture, cùng số liệu, trên mọi mặt.

Kiểm thửPlaywrightPuppeteer
Danh mục tĩnh (12 sản phẩm)12/12, recall 1.012/12, recall 1.0
Bài viết (tiêu đề + 3 đoạn)3/3, tách boilerplate3/3, tách boilerplate
Trang động JS (render gốc)8/8 + ảnh chụp màn hình8/8 + ảnh chụp màn hình
API JSON động8/8, recall 1.08/8, recall 1.0
Xử lý HTTP 500kiểm tra được, không ném lỗikiểm tra được, không ném lỗi
Đồ thị crawl (BFS viết tay)12 trang, độ sâu {0,1,2}12 trang, độ sâu {0,1,2}
Books to Scrape20 sản phẩm20 sản phẩm
Quotes JS (công khai)10 trích dẫn10 trích dẫn

Cả hai đều render JavaScript gốc mà không cần cấu hình đặc biệt nào. Cả hai đều chụp được ảnh full-page. Cả hai đều xử lý trang 500 bằng cách trả về một object response có thể kiểm tra thay vì ném exception — nghe thì nhỏ thôi, nhưng lại rất quan trọng khi bạn scrape ở quy mô lớn và muốn ghi lại trạng thái lỗi thay vì làm cả lượt chạy sập luôn.

Playwright and Puppeteer HTTP 500 no exception

Một lưu ý tôi sẽ nhắc lại vì rất dễ bị lạm dụng: đây là quan sát trên một máy, một lần chạy, không phải benchmark. Tôi không khẳng định công cụ nào nhanh hơn tính bằng mili giây, vì đồng hồ bấm thời gian cho từng trang trên một chiếc laptop không phải là kiểm tra tốc độ đúng nghĩa. Điều tôi khẳng định là hẹp hơn và có cơ sở hơn — về độ phủ dữ liệu trích xuất và hành vi render, trên tám kiểu trang khác nhau, chúng ngang nhau. Nếu bạn hy vọng một bên sẽ bứt lên trên một trang thực tế, thì điều đó đã không xảy ra.

Khác biệt duy nhất nên quyết định lựa chọn

Playwright vs Puppeteer browser and language difference

Điểm rẽ thật sự không nằm ở con số.

Nó nằm ở phạm vi hỗ trợ.

Playwright điều khiển ba engine — Chromium, Firefox và WebKit — qua một API, đồng thời có client chính thức cho Python, Java và .NET bên cạnh JavaScript. Đây là một thế mạnh được tài liệu hóa, và tôi muốn dùng từ "được tài liệu hóa" thật chính xác: trong lần kiểm này tôi chỉ chạy Chromium, nên tôi đang xem hỗ trợ ba engine của Playwright như một khả năng được công bố mà tôi chưa tự tay xác minh, chứ không phải thứ tôi đã kiểm nghiệm trực tiếp. Nếu bạn cần scrape một site hiển thị khác đi dưới WebKit của Safari, hoặc đội của bạn viết bằng Python, thì độ rộng đó là lý do để chọn Playwright.

Puppeteer thì ưu tiên Chrome, nhưng ở đây cách gọi tắt phổ biến lại không còn đúng hoàn toàn. "Chỉ Chrome" không còn chính xác nữa. Từ Puppeteer v23, nó đã có hỗ trợ Firefox đủ dùng trong môi trường sản xuất thông qua WebDriver BiDi, đồng thời vẫn mặc định dùng CDP cho Chrome để giữ nguyên các automation hiện có — một thay đổi được cả Chrome for Developers lẫn Mozilla ghi nhận. Phiên bản tôi kiểm tra (24.16.0) đã cao hơn v23 khá xa, nên khác biệt thực tế không phải là "Chrome so với ba engine". Nó là: Puppeteer hỗ trợ Chrome (CDP) và Firefox (BiDi) nhưng không có WebKit, và câu chuyện đa engine của nó còn non trẻ hơn Playwright. Engine mà Playwright có còn Puppeteer thì không chính là WebKit.

Đó là quyết định, khi đã cô đọng lại. Không phải tốc độ, không phải độ chính xác, không phải độ trung thực khi render — những thứ đó đều hòa. Đây là câu hỏi về phạm vi: bạn có cần phủ WebKit hoặc client ngôn ngữ không phải JavaScript không, hay Chrome và Firefox từ Node là đủ cho mục tiêu của bạn? Với phần lớn công việc scraping, cả hai đều đủ ngưỡng, và bạn đang chọn theo độ phù hợp với stack hơn là theo năng lực tuyệt đối.

Điều mà cả hai đều không làm

Playwright and Puppeteer hand-written BFS crawl

Cả hai công cụ đều để lại cùng một việc trên bàn của bạn: tổ chức crawl. Không bên nào có sẵn hàng đợi request, trình ghi dataset hay tự động điều tiết tốc độ. Bài kiểm thử đồ thị crawl của tôi — đi theo các link nội bộ, theo dõi độ sâu, không quay lại URL cũ — đều cần một thuật toán breadth-first search viết tay trong cả hai trường hợp. 12 trang, độ sâu {0,1,2}, BFS của tôi, cả hai lần.

Với vài trang thì như vậy là ổn; một BFS nhỏ chỉ cần hơn chục dòng. Nhưng khi crawl ở quy mô lớn — hàng trăm hoặc hàng nghìn URL, có khử trùng lặp, thử lại và độ trễ lịch sự — bạn sẽ либо phải tự xây phần đó, либо dùng một lớp bao bọc có sẵn. Crawlee làm đúng việc đó, cung cấp một lớp crawling thực thụ bên trên cả Playwright lẫn Puppeteer.

Đây không phải là lỗi, và tôi muốn gọi cho đúng: Playwright và Puppeteer là framework tự động hóa trình duyệt, không phải framework crawl. Việc thiếu hàng đợi là ranh giới phạm vi, không phải bug. Mô hình tư duy chính xác là xem các công cụ này như phần "thấy được trang" của một bộ scraper. Phần "đi qua cả site" bạn vẫn phải tự mang theo — tự viết, hoặc gắn thêm một wrapper đã có sẵn phần đó.

Cài đặt và lưu ý về phiên bản

Cài đặt gần như giống nhau. npm install sẽ kéo về thư viện cùng một binary trình duyệt, và binary đó mới là phần nặng — Puppeteer tự động đi kèm bản tải Chrome (trong lần chạy của tôi là cài sạch, không báo lỗ hổng), còn Playwright dùng npx playwright install riêng cho các bản dựng trình duyệt của nó. Cả hai đều không quá phiền, nhưng hãy tính trước thời gian tải xuống; dung lượng trình duyệt và chi phí cho mỗi trang chính là cái giá bạn trả cho việc render, so với một công cụ chỉ dùng HTTP.

Giờ là phần công bố tôi nợ bạn. Tôi đã test Playwright 1.56.0 so với bản mới nhất 1.61.1, và Puppeteer 24.16.0 so với bản npm mới nhất 25.3.0 — tức Puppeteer chậm hơn một major version, tất cả đều tính đến 2026-07-09. Các API tôi sử dụng đều ổn định qua những khoảng cách đó, nên kết quả vẫn giữ nguyên. Nhưng nếu bạn đọc bài này sau một thời gian, hãy chạy lại trên phiên bản hiện tại trước khi đặt cược các con số chính xác vào chúng. Và nói thêm một lần nữa: tôi chỉ chạy Chromium trên Playwright, nên tôi không đưa ra bất kỳ khẳng định nào về độ tương đương của Firefox hay WebKit ngoài việc "điều đó đã được tài liệu hóa."

Playwright và Puppeteer: ưu và nhược điểm

Kết quả hòa khiến danh sách ưu/nhược điểm bớt là câu chuyện thắng thua, mà nghiêng về việc bạn sẵn sàng gắn bó với điều gì.

Playwright

  • Ưu điểm: hỗ trợ ba engine được tài liệu hóa (Chromium, Firefox, WebKit) qua một API; client chính thức cho Python, Java và .NET; render JS gốc với độ bao phủ đầy đủ; đang mở rộng khá tích cực.
  • Nhược điểm: không có sẵn hàng đợi crawl; trình duyệt nặng và tốn chi phí theo mỗi trang; bài test này chỉ chạy Chromium; phiên bản tôi dùng vẫn thấp hơn bản mới nhất.

Puppeteer

  • Ưu điểm: tự động hóa Chrome trưởng thành và ổn định qua CDP; render JS gốc với độ bao phủ đầy đủ; xử lý 500 gọn gàng (trả về response object, không ném lỗi); hệ sinh thái sâu và quen thuộc; đã có hỗ trợ Firefox qua WebDriver BiDi từ v23.
  • Nhược điểm: ưu tiên Chrome và Node, không có WebKit; không có sẵn hàng đợi crawl; trình duyệt nặng; phiên bản tôi dùng thấp hơn bản npm mới nhất một major version.

Ai nên chọn gì

Playwright vs Puppeteer choose by stack

Chọn Puppeteer nếu bạn làm việc trong Node, các site mục tiêu render tốt trên Chrome (đa số là vậy), và bạn muốn một thư viện trưởng thành, tập trung, hệ sinh thái mạnh, với ít hơn một chiều phức tạp để cân nhắc. Tùy chọn Firefox qua BiDi vẫn có đó nếu sau này bạn cần.

Chọn Playwright nếu bạn cần phủ WebKit, muốn viết scraper bằng Python hoặc .NET, hoặc muốn đặt cược vào dự án có phạm vi engine và ngôn ngữ rộng hơn. Chỉ riêng độ phù hợp ngôn ngữ thôi đã là lý do rõ ràng nhất khiến một team Python chọn Playwright.

Và đây là câu trả lời thứ ba mà các bài so sánh thường bỏ qua: chọn không bên nào nếu trang của bạn thực ra không cần JavaScript để hiển thị dữ liệu. Nếu một request HTTP cộng với parser đã lấy được nội dung bạn cần, thì headless browser là quá nặng và quá thừa — đó là một nhóm công cụ khác, và dùng browser thật trong trường hợp đó chỉ tốn RAM cùng thời gian cài đặt vô ích.

Khi nào một API được quản lý phù hợp, bao gồm Thunderbit

Dùng thử Thunderbit để trích xuất dữ liệu web

Cả Playwright lẫn Puppeteer đều là thư viện mã nguồn mở miễn phí mà bạn tự chạy và tự duy trì. Bạn chịu trách nhiệm môi trường trình duyệt, các bản cập nhật, mã crawl bạn ghép thêm, và cuộc đua chống bot. Với nhiều dự án, việc tự sở hữu như vậy là hoàn toàn đúng, và bài viết này không nhằm phản đối nó.

Nhưng hãy nhìn xem bao nhiêu phần của công việc scraping thực sự nằm ngoài các công cụ này. Chúng render trang rất tốt; nhưng chúng không xếp hàng URL, không tự xoay vòng khi gặp chặn, không trả cho bạn JSON có cấu trúc, và bạn phải giữ cả cụm trình duyệt luôn hoạt động. Đó là một lớp khác trong stack so với một dịch vụ trích xuất được quản lý, và rất đáng nói rõ cho các developer đang cân nhắc tự xây hay mua. Bộ công cụ developer của Thunderbit của chúng tôi nằm ở lớp đó: POST /distill biến một trang thành Markdown sạch, sẵn sàng cho LLM, còn POST /extract trả về JSON có cấu trúc theo schema bạn định nghĩa, với render JavaScript, xử lý anti-bot và CAPTCHA được quản lý ở phía server thay vì trên máy tính của bạn. Có một Thunderbit MCP server dành cho AI agents và coding assistants (trong đó thunderbit_suggest_fields miễn phí trước khi bạn tiêu tốn bất kỳ gì), và một CLI qua npx @thunderbit/thunderbit-cli cho CI và cron.

Tôi không định nói rằng cách đó tốt hơn tuyệt đối — nó là một kiểu đánh đổi khác. Với Playwright hoặc Puppeteer, bạn tự sở hữu phần render và mọi thứ bạn xây xung quanh nó, với chi phí mỗi lần gọi bằng không. Với một API được quản lý, bạn chuyển gánh nặng render, chống bot và hạ tầng crawl sang dịch vụ khác, và trả tiền theo request (trong trường hợp của Thunderbit là tính theo lần gọi — một credit cho distill, hai mươi cho extract — không tính theo số dòng). Dự án nhỏ, tự host, thích tự quản lý browser? Những thư viện này là công cụ đúng. Muốn scale, và không muốn vận hành cả một đội headless browser kèm crawler và lớp xoay vòng chặn? Dùng đường managed sẽ xóa bỏ cả một hạng mục công việc.

Ở bức tranh rộng hơn, đội của chúng tôi cũng đã thử cách tiếp cận hai engine của Crawlee và một nhóm framework thiên về HTTP trên cùng bộ fixture này, đây là điểm tiếp theo hợp lý nếu bạn đã quyết rằng một trình duyệt đầy đủ là nhiều hơn mức trang của bạn cần.

Kết luận

Nên dùng Playwright hay Puppeteer? Với việc render các trang JavaScript, dùng bên nào cũng được — chúng hòa trên mọi bài test quan trọng ở đây, nên bạn không phải đánh đổi năng lực chỉ vì chọn theo yếu tố khác. Chọn Puppeteer nếu Chrome và Firefox từ Node phù hợp với bạn và bạn thích sự trưởng thành, tập trung. Chọn Playwright nếu bạn cần phủ WebKit hoặc client không phải JavaScript.

Có hai điều mà các bài so sánh thường hay bỏ qua nhưng rất đáng nhớ. Thứ nhất, trên các tác vụ scrape thực tế, hai công cụ này thực sự hòa nhau, nên đừng quá băn khoăn về một khoảng cách hiệu năng vốn không xuất hiện trong tám bài kiểm thử khác nhau. Thứ hai, cả hai đều không phải crawler — chúng render trang, còn phần crawl là việc của bạn hoặc của một lớp bao như Crawlee. Làm rõ hai điều đó, khớp phạm vi với stack của bạn, và quyết định sẽ trở nên rất nhỏ. Việc chọn engine quan trọng ít hơn nhiều so với nửa công việc mà cả hai không làm thay bạn.

Tìm hiểu thêm

Dùng thử Thunderbit để trích xuất dữ liệu web Get Started Free

Câu hỏi thường gặp

Playwright hay Puppeteer nhanh hơn cho web scraping? Trên các fixture giống hệt nhau, chúng gần như hòa tuyệt đối — cùng độ bao phủ trên trang tĩnh (12/12), trang động (8/8), và trích xuất từ API JSON, cùng render gốc, cùng xử lý 500. Đây là quan sát một lần chạy trên một máy, không phải benchmark, nên khác biệt thời gian mỗi trang không phải phép đo tốc độ đáng tin. Hãy chọn theo phạm vi và ngôn ngữ, chứ không theo một khoảng cách tốc độ vốn không hề xuất hiện.

Khác biệt thực sự giữa Playwright và Puppeteer là gì? Là phạm vi engine và ngôn ngữ. Playwright điều khiển Chromium, Firefox và WebKit qua một API, với client cho Python, Java và .NET. Puppeteer ưu tiên Chrome qua CDP, có hỗ trợ Firefox được ghi nhận qua WebDriver BiDi từ v23, nhưng không có WebKit, và chạy trên Node. Cả hai đều render JavaScript gốc, và cả hai đều không có sẵn cơ chế crawl orchestration.

Tôi có thể crawl toàn bộ một site bằng Playwright hoặc Puppeteer không? Không có sẵn ngay từ đầu. Cả hai đều không có request queue, dataset writer hay auto-throttling — bài test đồ thị crawl của tôi cần một BFS viết tay trong cả hai trường hợp, 12 trang ở các độ sâu {0,1,2}. Nếu cần quy mô lớn, hãy thêm một lớp crawling như Crawlee, vốn bao bọc cả hai engine với hạ tầng crawl thực thụ.

Scraping có bắt buộc phải dùng công cụ trình duyệt không? Chỉ khi trang cần JavaScript để lộ dữ liệu. Nếu một request HTTP cộng với parser đã trả về nội dung bạn muốn, thì headless browser là quá tốn kém và thừa thãi — hãy dùng công cụ thiên về HTTP thay vì mang cả gánh nặng trình duyệt vào.

Một team Python nên chọn cái nào? Playwright, vì nó có client Python chính thức. Puppeteer là công cụ thiên về Node, nên nếu dùng từ Python thì bạn sẽ phải tự xây cầu nối và tự bảo trì nó. Sự phù hợp ngôn ngữ này là một trong những lý do rõ ràng nhất để chọn Playwright thay vì Puppeteer.

Ke
Ke
CTO tại Thunderbit | Chuyên gia Khoa học Dữ liệu cấp cao & ML Với gần một thập kỷ kinh nghiệm trong học máy và khoa học dữ liệu, Ke Shen là cựu sinh viên Đại học Columbia và từng là Chuyên gia Khoa học Dữ liệu cấp cao tại Walmart Labs. Sở hữu chuyên môn sâu về Python, R, Java và Thống kê, được đồng nghiệp công nhận, anh chia sẻ những góc nhìn thực chiến về cách đưa các thuật toán AI phức tạp từ lý thuyết vào kiến trúc sẵn sàng cho môi trường sản xuất.

Thử Thunderbit

Scrape lead và dữ liệu khác chỉ với 2 cú nhấp. Vận hành bằng AI.

Nhận Thunderbit Miễn phí
Trích xuất dữ liệu bằng AI
Dễ dàng chuyển dữ liệu sang Google Sheets, Airtable hoặc Notion
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week