nightmare、playwright、puppeteer 和 selenium-webdriver 都是用于控制浏览器进行自动化测试、爬虫或生成截图的 Node.js 库。selenium-webdriver 是历史最悠久的标准方案,支持多语言和多浏览器;puppeteer 由 Google 维护,专注于 Chromium 生态;playwright 由 Microsoft 开发,支持多浏览器并提供了现代化的自动等待机制;而 nightmare 基于 Electron,目前已不再维护。这些工具虽然目标相似,但在架构设计、浏览器支持范围和长期维护性上存在显著差异。
在 Node.js 生态中,控制浏览器进行自动化测试或数据抓取是一项常见需求。nightmare、playwright、puppeteer 和 selenium-webdriver 是四个最具代表性的解决方案。虽然它们都能完成“打开浏览器、点击按钮、获取内容”这类任务,但在底层实现、维护状态和开发体验上有着本质区别。作为架构师,我们需要从工程落地的角度深入分析它们的差异。
这是选型时最关键的决策点。一个不再维护的库会带来安全隐患和技术债务。
nightmare 已经停止维护。
// nightmare: 已废弃,仅作历史参考
const Nightmare = require('nightmare');
const nightmare = Nightmare({ show: false });
nightmare
.goto('https://example.com')
.click('button')
.end()
.then(function(result) {
console.log(result);
});
playwright 处于活跃维护中。
// playwright: 现代且活跃
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
await browser.close();
})();
puppeteer 处于活跃维护中。
// puppeteer: 现代且活跃
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
await browser.close();
})();
selenium-webdriver 处于活跃维护中。
// selenium-webdriver: 标准且稳定
const { Builder, By } = require('selenium-webdriver');
(async function example() {
let driver = await new Builder().forBrowser('chrome').build();
await driver.get('https://example.com');
await driver.quit();
})();
不同的业务场景需要不同的浏览器内核支持。
playwright 支持三大内核。
// playwright: 多浏览器支持
const { chromium, firefox, webkit } = require('playwright');
async function testAll() {
for (const browserType of [chromium, firefox, webkit]) {
const browser = await browserType.launch();
// 运行测试逻辑...
await browser.close();
}
}
puppeteer 主要支持 Chromium。
// puppeteer: 专注 Chromium
const puppeteer = require('puppeteer');
(async () => {
// 默认启动 Chromium
const browser = await puppeteer.launch({ product: 'chrome' });
// Firefox 支持有限且配置复杂
})();
selenium-webdriver 支持所有主流浏览器。
// selenium-webdriver: 广泛支持
const { Builder } = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');
const firefox = require('selenium-webdriver/firefox');
// 启动 Chrome
let driverChrome = await new Builder().forBrowser('chrome').build();
// 启动 Firefox
let driverFirefox = await new Builder().forBrowser('firefox').build();
nightmare 仅支持 Electron。
// nightmare: 仅 Electron
const Nightmare = require('nightmare');
// 无法切换浏览器内核,仅限于 Electron 环境
const nightmare = Nightmare({ show: false });
现代 Web 应用大量使用异步加载,如何处理元素等待是测试稳定性的核心。
playwright 内置智能自动等待。
waitFor 代码。// playwright: 自动等待
const page = await browser.newPage();
await page.goto('https://example.com');
// 自动等待按钮可见且可点击
await page.click('#submit-button');
puppeteer 需要部分手动等待。
waitForSelector,但点击操作本身不总是隐含等待。// puppeteer: 需显式等待
const page = await browser.newPage();
await page.goto('https://example.com');
// 通常需要先等待元素出现
await page.waitForSelector('#submit-button');
await page.click('#submit-button');
selenium-webdriver 需要显式等待配置。
WebDriverWait 来保证稳定性。// selenium-webdriver: 显式等待
const { until } = require('selenium-webdriver');
await driver.get('https://example.com');
// 必须显式定义等待条件
let element = await driver.wait(until.elementLocated(By.id('submit-button')));
await element.click();
nightmare 链式调用隐含等待。
// nightmare: 链式隐含等待
nightmare
.goto('https://example.com')
.wait('#submit-button') // 需显式调用 wait
.click('#submit-button');
这些功能常用于生成报告或爬虫存档。
playwright 支持全功能截图与 PDF。
// playwright: 截图与 PDF
await page.screenshot({ path: 'example.png', fullPage: true });
await page.pdf({ path: 'report.pdf', format: 'A4' });
puppeteer 截图与 PDF 是其强项。
// puppeteer: 截图与 PDF
await page.screenshot({ path: 'example.png', fullPage: true });
await page.pdf({ path: 'report.pdf', format: 'A4' });
selenium-webdriver 仅支持截图。
// selenium-webdriver: 仅截图
let png = await driver.takeScreenshot();
// 需要手动处理 png 数据写入文件
// 不支持 page.pdf()
nightmare 支持截图。
// nightmare: 仅截图
await nightmare.screenshot('example.png');
// 不支持 PDF
| 特性 | playwright | puppeteer | selenium-webdriver | nightmare |
|---|---|---|---|---|
| 维护状态 | ✅ 活跃 (Microsoft) | ✅ 活跃 (Google) | ✅ 活跃 (社区标准) | ❌ 已停止维护 |
| 浏览器内核 | Chromium, Firefox, WebKit | 主要 Chromium | 所有 (通过 Driver) | Electron 仅 |
| 自动等待 | ✅ 智能内置 | ⚠️ 部分支持 | ❌ 需手动配置 | ⚠️ 链式隐含 |
| API 风格 | 现代 Promise/Async | 现代 Promise/Async | 经典 Promise/Async | 链式调用 |
| PDF 支持 | ✅ 支持 | ✅ 支持 | ❌ 不支持 | ❌ 不支持 |
| 适用场景 | 端到端测试、跨浏览器 | 爬虫、PDF、Chrome 测试 | 传统测试、多语言协作 | 旧项目维护 (不推荐) |
playwright 是现代端到端测试的首选 🏆。
puppeteer 是 Chrome 生态工具的最佳搭档 🛠️。
selenium-webdriver 是企业遗留系统的稳定基石 🏢。
nightmare 应被逐步淘汰 🗑️。
在选择浏览器自动化库时,维护状态和浏览器覆盖范围是两个决定性因素。playwright 凭借其现代化的设计和跨浏览器能力,已成为大多数新项目的默认选择。puppeteer 在 Chrome 特定任务上依然保持优势。selenium-webdriver 则继续服务于需要广泛兼容性和标准协议的场景。而 nightmare 已完成了它的历史使命,不应再出现在新的技术栈中。
如果需要跨浏览器测试(包括 WebKit、Firefox 和 Chromium)或构建高可靠性的端到端测试,请选择 playwright。它提供了强大的自动等待功能、网络拦截能力和现代化的 API 设计,非常适合现代 Web 应用的复杂交互场景。
如果项目主要依赖 Chrome 或 Chromium,或者需要生成 PDF、截取页面截图以及进行无头爬虫开发,puppeteer 是理想选择。它与 Chrome DevTools 协议深度集成,启动速度快,且在 Google 生态内更新及时。
当需要支持非 Chromium 内核的老旧浏览器,或者团队已经建立了基于 Selenium Grid 的基础设施时,选择 selenium-webdriver。它是行业标准,语言绑定丰富,但配置相对繁琐,运行速度通常慢于现代无头浏览器方案。
不建议在新项目中选择 nightmare。该库已停止维护多年,基于旧版 Electron,存在安全漏洞且不支持现代浏览器特性。如果维护旧项目,建议尽快迁移到 playwright 或 puppeteer 以获得更好的稳定性和支持。
Playwright is a framework for web automation and testing. It drives Chromium, Firefox, and WebKit with a single API — in your tests, in your scripts, and as a tool for AI agents.
Choose the path that fits your workflow:
| Best for | Install | |
|---|---|---|
| Playwright Test | End-to-end testing | npm init playwright@latest |
| Playwright CLI | Coding agents (Claude Code, Copilot) | npm i -g @playwright/cli@latest |
| Playwright MCP | AI agents and LLM-driven automation | npx @playwright/mcp@latest |
| Playwright Library | Browser automation scripts | npm i playwright |
| VS Code Extension | Test authoring and debugging in VS Code | Install from Marketplace |
Playwright Test is a full-featured test runner built for end-to-end testing. It runs tests across Chromium, Firefox, and WebKit with full browser isolation, auto-waiting, and web-first assertions.
npm init playwright@latest
Or add manually:
npm i -D @playwright/test
npx playwright install
import { test, expect } from '@playwright/test';
test('has title', async ({ page }) => {
await page.goto('https://playwright.dev/');
await expect(page).toHaveTitle(/Playwright/);
});
test('get started link', async ({ page }) => {
await page.goto('https://playwright.dev/');
await page.getByRole('link', { name: 'Get started' }).click();
await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
});
npx playwright test
Tests run in parallel across all configured browsers, in headless mode by default. Each test gets a fresh browser context — full isolation with near-zero overhead.
Auto-wait and web-first assertions. No artificial timeouts. Playwright waits for elements to be actionable, and assertions automatically retry until conditions are met.
Locators. Find elements with resilient locators that mirror how users see the page:
page.getByRole('button', { name: 'Submit' })
page.getByLabel('Email')
page.getByPlaceholder('Search...')
page.getByTestId('login-form')
Test isolation. Each test runs in its own browser context — equivalent to a fresh browser profile. Save authentication state once and reuse it across tests:
// Save state after login
await page.context().storageState({ path: 'auth.json' });
// Reuse in other tests
test.use({ storageState: 'auth.json' });
Tracing. Capture execution traces, screenshots, and videos on failure. Inspect every action, DOM snapshot, network request, and console message in the Trace Viewer:
// playwright.config.ts
export default defineConfig({
use: {
trace: 'on-first-retry',
},
});
npx playwright show-trace trace.zip
Parallelism. Tests run in parallel by default across all configured browsers.
Playwright CLI is a command-line interface for browser automation designed for coding agents. It's more token-efficient than MCP — commands avoid loading large tool schemas and accessibility trees into the model context.
npm install -g @playwright/cli@latest
Optionally install skills for richer agent integration:
playwright-cli install --skills
Point your coding agent at a task:
Test the "add todo" flow on https://demo.playwright.dev/todomvc using playwright-cli.
Take screenshots for all successful and failing scenarios.
Or run commands directly:
playwright-cli open https://demo.playwright.dev/todomvc/ --headed
playwright-cli type "Buy groceries"
playwright-cli press Enter
playwright-cli screenshot
Use playwright-cli show to open a visual dashboard with live screencast previews of all running browser sessions. Click any session to zoom in and take remote control.
playwright-cli show
Full CLI documentation | GitHub
The Playwright MCP server gives AI agents full browser control through the Model Context Protocol. Agents interact with pages using structured accessibility snapshots — no vision models or screenshots required.
Add to your MCP client (VS Code, Cursor, Claude Desktop, Windsurf, etc.):
{
"mcpServers": {
"playwright": {
"command": "npx",
"args": ["@playwright/mcp@latest"]
}
}
}
One-click install for VS Code:
For Claude Code:
claude mcp add playwright npx @playwright/mcp@latest
Ask your AI assistant to interact with any web page:
Navigate to https://demo.playwright.dev/todomvc and add a few todo items.
The agent sees the page as a structured accessibility tree:
- heading "todos" [level=1]
- textbox "What needs to be done?" [ref=e5]
- listitem:
- checkbox "Toggle Todo" [ref=e10]
- text: "Buy groceries"
It uses element refs like e5 and e10 to click, type, and interact — deterministically and without visual ambiguity. Tools cover navigation, form filling, screenshots, network mocking, storage management, and more.
Full MCP documentation | GitHub
Use playwright as a library for browser automation scripts — web scraping, PDF generation, screenshot capture, and any workflow that needs programmatic browser control without a test runner.
npm i playwright
Take a screenshot:
import { chromium } from 'playwright';
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://playwright.dev/');
await page.screenshot({ path: 'screenshot.png' });
await browser.close();
Generate a PDF:
import { chromium } from 'playwright';
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://playwright.dev/');
await page.pdf({ path: 'page.pdf', format: 'A4' });
await browser.close();
Emulate a mobile device:
import { chromium, devices } from 'playwright';
const browser = await chromium.launch();
const context = await browser.newContext(devices['iPhone 15']);
const page = await context.newPage();
await page.goto('https://playwright.dev/');
await page.screenshot({ path: 'mobile.png' });
await browser.close();
Intercept network requests:
import { chromium } from 'playwright';
const browser = await chromium.launch();
const page = await browser.newPage();
await page.route('**/*.{png,jpg,jpeg}', route => route.abort());
await page.goto('https://playwright.dev/');
await browser.close();
Library documentation | API reference
The Playwright VS Code extension brings test running, debugging, and code generation directly into your editor.
Run and debug tests from the editor with a single click. Set breakpoints, inspect variables, and step through test execution with a live browser view.
Generate tests with CodeGen. Click "Record new" to open a browser — navigate and interact with your app while Playwright writes the test code for you.
Pick locators. Hover over any element in the browser to see the best available locator, then click to copy it to your clipboard.
Trace Viewer integration. Enable "Show Trace Viewer" in the sidebar to get a full execution trace after each test run — DOM snapshots, network requests, console logs, and screenshots at every step.
Install the extension | VS Code guide
| Linux | macOS | Windows | |
|---|---|---|---|
| Chromium1 151.0.7922.34 | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| WebKit 26.5 | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Firefox 153.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: |
Headless and headed execution on all platforms. 1 Uses Chrome for Testing by default.
Playwright is also available for Python, .NET, and Java.