When we think of Playwright, we usually picture UI automation — clicking buttons, filling forms, and capturing screenshots.
But Playwright has a powerful secret: you can also test APIs directly — and combine them with your UI tests to create end-to-end magic.
Today, I’ll walk you through how I use Playwright for API testing, data setup, and UI+API hybrid validation — all in one clean framework.
When to Use API Testing in Playwright
Here’s when I reach for Playwright’s API capabilities:
Prepping test data before UI test runs
Validating backend responses during a UI journey
Testing standalone APIs (no UI required)
Speeding up test flows (skip UI setup where possible)
Basic API Test with Playwright
Playwright gives you direct access to API requests via request.newContext():
ts
import { test, expect, request } from ‚@playwright/test‘;
test(‚GET users API returns 200‘, async () => {
const apiContext = await request.newContext();
const response = await apiContext.get(‚https://api.example.com/users‘);
expect(response.status()).toBe(200);
const data = await response.json();
expect(data.length).toBeGreaterThan(0);
});
Fast, simple, and powerful — no extra libraries needed.
Combine API + UI in One Test
Here’s a real-world flow:
Create a user via API
Login through UI
Verify dashboard loads
ts
test(‚Create user via API and login via UI‘, async ({ page, request }) => {
const newUser = {
username: ‚qauser123‘,
password: ’secretpass‘
};
const res = await request.post(‚/api/users‘, { data: newUser });
expect(res.ok()).toBeTruthy();
await page.goto(‚/login‘);
await page.fill(‚#username‘, newUser.username);
await page.fill(‚#password‘, newUser.password);
await page.click(‚button[type=“submit“]‘);
await expect(page).toHaveURL(‚/dashboard‘);
});
This approach speeds up tests and removes the need for seed databases or manual setup.
⚙️ Using API Fixtures for Test Setup
Make reusable API helpers:
ts
export async function createTestUser(request, role = ‚user‘) {
const response = await request.post(‚/api/users‘, {
data: { username: user_${Date.now()}
, password: ‚pass123‘, role }
});
return await response.json();
}
Then call it in your tests:
ts
const user = await createTestUser(request, ‚admin‘);
📈 Validating Backend State During UI Flows
Example: After submitting a form in the UI, check the record via API:
ts
await page.click(‚text=Submit‘);
const record = await request.get(/api/records/${id}
);
expect((await record.json()).status).toBe(’submitted‘);
API Auth? Playwright Supports It
Use API tokens or login requests:
ts
const apiContext = await request.newContext({
baseURL: ‚https://api.example.com‚,
extraHTTPHeaders: {
Authorization: Bearer ${token}
}
});
Faster tests: Use API when UI is unnecessary.
Cleaner setup: Pre-seed data without UI clicks.
Better coverage: Test flows that touch backend + frontend together.
All-in-one tool: No need for separate Postman/newman or REST clients.
Organize API Utilities
Structure your tests like this:
pgsql
tests/
├── api/
│ ├── userApi.ts
│ ├── recordApi.ts
├── ui/
│ ├── login.spec.ts
│ └── dashboard.spec.ts
Each API file contains reusable helpers to keep your test logic clean and DRY.
Playwright isn’t just a browser automation tool — it’s a full-stack test engine. When you use it to test APIs and UI together, you unlock faster, smarter, and more stable tests.