Q33 of 42 · Playwright
Compare Playwright's APIRequestContext for backend testing vs a separate API test framework.
Short answer
Short answer: `APIRequestContext` (`request` fixture or `page.request`) makes HTTP calls with cookie/storage sharing with browser tests — ideal for setup, teardown, and hybrid API+UI tests. A dedicated API framework (Postman, REST Assured, Hurl, supertest) is better for pure API contract testing because of richer schema/assertion tooling.
Detail
Playwright ships APIRequestContext — the request fixture in tests. It's a fully-featured HTTP client that shares cookies and auth state with the page:
test('hybrid API + UI test', async ({ page, request }) => {
// API setup — fast and reliable
const order = await request.post('/api/orders', {
data: { items: [...], total: 100 },
});
expect(order.status()).toBe(201);
const { id } = await order.json();
// UI verification
await page.goto(`/orders/${id}`);
await expect(page.getByTestId('order-status')).toHaveText('Pending');
});
Strengths:
- Cookie sharing with the browser context — log in via UI, hit APIs as the same user.
- Same fixture / runner / report as your E2E. No tool sprawl.
- TypeScript types match the rest of your test code.
- Trace integration — API calls show up in the Playwright trace viewer.
Weaknesses (vs a dedicated API framework):
- Schema validation isn't built in. You'd add Ajv or Zod yourself. REST Assured / Postman ship it.
- Contract testing (Pact) integrates better outside Playwright.
- Performance / load testing — Playwright isn't optimised for hammering endpoints; k6 or JMeter is.
- Visualisation / collections — Postman's collections + Newman runner is a richer authoring environment for non-engineers.
The pragmatic split:
- Use
APIRequestContextfor: test setup/teardown, hybrid scenarios, smoke checks against APIs. - Use a dedicated API framework for: pure API contract suites, schema-strict regression, performance, broader stakeholder authoring.
A common architecture: Playwright owns the E2E + hybrid layer; a separate api-tests/ package using something like supertest + zod + vitest covers the deep API regression. Both contribute to release confidence.
Watch-out for hybrid tests: don't try to test the API contract via Playwright. expect(response.status()).toBe(201) is fine, but full schema validation, error case enumeration, and contract pinning belong in dedicated API tests where the assertion vocabulary is richer.
// EXAMPLE
hybrid.spec.ts
import { test, expect } from '@playwright/test';
test('checkout — API setup, UI verification', async ({ page, request }) => {
// 1. Auth (shared cookie state)
await request.post('/api/login', {
data: { email: 'alice@x.com', password: 'pwd' },
});
// 2. Seed order via API (fast, deterministic)
const create = await request.post('/api/orders', {
data: {
items: [{ sku: 'p1', qty: 2 }],
shippingAddress: { country: 'GB', postcode: 'SW1A 1AA' },
},
});
expect(create.status()).toBe(201);
const { id } = await create.json();
// 3. UI assertion
await page.goto(`/orders/${id}`);
await expect(page.getByTestId('status')).toHaveText('Pending');
});