Playwright is not limited to browser automation and UI testing. It also provides powerful capabilities for API testing through the built-in APIRequestContext.
Using Playwright, testers and developers can send HTTP requests, validate responses, verify status codes, inspect response bodies, and perform end-to-end testing by combining API and UI workflows within the same framework.
What is API Testing?
API Testing is the process of validating Application Programming Interfaces (APIs) to ensure they function correctly, return expected responses, handle errors properly, and meet performance and security requirements.
Common API operations include:
- GET – Retrieve data
- POST – Create data
- PUT – Update data
- PATCH – Modify data partially
- DELETE – Remove data
Why Use Playwright for API Testing?
- Built-in API testing support
- No additional libraries required
- Supports REST API testing
- Easy integration with UI tests
- Fast execution
- Powerful assertions
- Authentication support
- Parallel execution capabilities
Prerequisites
Install Playwright:
npm init playwright@latest
Or:
npm install -D @playwright/test
Importing Playwright API Utilities
import { test, expect } from '@playwright/test';
The request fixture is automatically available in Playwright tests.
Creating Your First API Test
GET Request Example
import { test, expect } from '@playwright/test';
test('Get User Details', async ({ request }) => {
const response = await request.get(
'https://jsonplaceholder.typicode.com/users/1'
);
expect(response.status()).toBe(200);
});
Validating Response Status Code
expect(response.status()).toBe(200);
Common Status Codes:
| Status Code | Meaning |
|---|---|
| 200 | Success |
| 201 | Created |
| 204 | No Content |
| 400 | Bad Request |
| 401 | Unauthorized |
| 404 | Not Found |
| 500 | Server Error |
Reading Response Body
const data = await response.json();
console.log(data);
Validating Response Data
const data = await response.json();
expect(data.id).toBe(1);
expect(data.name).toBe('Leanne Graham');
POST Request Example
POST requests are used to create new resources.
test('Create User', async ({ request }) => {
const response = await request.post(
'https://jsonplaceholder.typicode.com/users',
{
data: {
name: 'John',
email: 'john@example.com'
}
}
);
expect(response.status()).toBe(201);
});
Validating POST Response
const responseData = await response.json();
expect(responseData.name).toBe('John');
expect(responseData.email)
.toBe('john@example.com');
PUT Request Example
PUT requests are used to update an existing resource.
test('Update User', async ({ request }) => {
const response = await request.put(
'https://jsonplaceholder.typicode.com/users/1',
{
data: {
name: 'Updated User'
}
}
);
expect(response.status()).toBe(200);
});
PATCH Request Example
PATCH requests update specific fields of a resource.
test('Modify User', async ({ request }) => {
const response = await request.patch(
'https://jsonplaceholder.typicode.com/users/1',
{
data: {
name: 'Modified User'
}
}
);
expect(response.ok()).toBeTruthy();
});
DELETE Request Example
DELETE requests remove resources.
test('Delete User', async ({ request }) => {
const response = await request.delete(
'https://jsonplaceholder.typicode.com/users/1'
);
expect(response.status()).toBe(200);
});
Using Headers in Requests
const response = await request.get(
'https://api.example.com/users',
{
headers: {
Authorization: 'Bearer token123',
Accept: 'application/json'
}
}
);
Authentication Example
Bearer Token Authentication
test('Authenticated API Request',
async ({ request }) => {
const response = await request.get(
'https://api.example.com/profile',
{
headers: {
Authorization:
'Bearer your_access_token'
}
}
);
expect(response.status()).toBe(200);
});
Query Parameters
const response = await request.get(
'https://api.example.com/users',
{
params: {
page: 1,
limit: 10
}
}
);
Working with Request Context
A request context can be reused across multiple API tests.
import { request } from '@playwright/test';
const apiContext =
await request.newContext({
baseURL: 'https://api.example.com'
});
Using Base URL
const apiContext =
await request.newContext({
baseURL: 'https://api.example.com'
});
const response =
await apiContext.get('/users');
Validating Response Headers
expect(
response.headers()['content-type']
).toContain('application/json');
Checking Response Time
const startTime = Date.now();
const response =
await request.get('/users');
const duration =
Date.now() - startTime;
expect(duration)
.toBeLessThan(2000);
Combining API and UI Testing
One of Playwright's strongest features is combining API and UI testing in a single framework.
test('Create User Using API and Verify UI',
async ({ request, page }) => {
await request.post('/users', {
data: {
name: 'John'
}
});
await page.goto('/users');
await expect(
page.getByText('John')
).toBeVisible();
});
Common Assertions for API Testing
| Assertion | Purpose |
|---|---|
| toBe() | Validate exact value |
| toContain() | Validate partial value |
| toEqual() | Validate object equality |
| toBeTruthy() | Validate true condition |
| toBeFalsy() | Validate false condition |
Error Handling Example
test('Handle API Errors',
async ({ request }) => {
const response =
await request.get('/invalid-endpoint');
expect(response.status())
.toBe(404);
});
Best Practices
- Validate both status codes and response data.
- Use reusable request contexts.
- Store sensitive credentials securely.
- Verify response headers when required.
- Keep test data independent.
- Use API tests to prepare test data for UI tests.
- Validate error scenarios in addition to success scenarios.
- Use environment variables for URLs and tokens.
Advantages of API Testing in Playwright
- Fast execution speed
- No browser dependency
- Built-in support
- Powerful assertion library
- Easy integration with UI automation
- Parallel execution support
- Simple setup and maintenance
Conclusion
Playwright provides a robust and efficient solution for API testing through its built-in request capabilities. Whether you're validating REST APIs, performing authentication testing, verifying response data, or combining API and UI workflows, Playwright enables end-to-end testing within a single framework. This reduces tool complexity and helps teams build faster, more reliable automated test suites.