Practice Hub
Score: 0 / 15
Challenge 1BeginnerHTTP Status
Solved
What status code does a successful POST that creates a resource return?
You send a POST request to create a new user. The operation succeeds and the resource is created. What HTTP status code should you expect?
Answer: B — 201 Created
201 Created is the correct status for a POST that successfully creates a new resource. The response typically includes the created resource in the body and a Location header pointing to the new resource's URL. 200 OK is for general success (GET, PUT). 202 Accepted means processing is async. 204 means success with no body (common for DELETE).
Challenge 2BeginnerHTTP Status
Solved
What is the difference between 401 and 403?
Two requests fail with authentication/authorization errors. One returns 401, the other 403. What do they mean?
Answer: B — 401 = unauthenticated; 403 = unauthorized
401 Unauthorized: The request lacks valid authentication credentials. "You haven't proven who you are." Retrying with valid credentials may succeed. 403 Forbidden: The request is authenticated but the user lacks permission to perform this action. "We know who you are, but you can't do this." Retrying with the same credentials won't help — you need different permissions.
Challenge 3Beginnerrequest fixture
Solved
What type is the built-in request fixture?
In a Playwright test function, { request } is destructured. What is the TypeScript type of request?
Answer: B — APIRequestContext
The built-in request fixture is of type APIRequestContext. It provides methods: get(), post(), put(), patch(), delete(), head(), fetch(). It does not open a browser — it's a pure HTTP client. It respects baseURL from config and any extraHTTPHeaders defined at the context level.
Challenge 4BeginnerResponse
Solved
What does response.status() return?
You call const response = await request.post('/api/users', {...}). What does response.status() return?
Answer: B — numeric HTTP status code
response.status() is a synchronous method that returns the HTTP status code as a number (e.g., 200, 201, 404). Use it with expect(response.status()).toBe(201). Note that response.ok() is a convenience boolean for 200–299. response.statusText() returns the text phrase like "Created".
Challenge 5BeginnerRequest Body
Solved
How do you send a JSON body in a Playwright API POST request?
Which option key sends a JavaScript object as a JSON request body?
const response = await request.post('/api/users', {
  ???: { name: 'Alice', role: 'tester' }
});
Answer: C — data: key
In Playwright's API request methods, the data key accepts a JavaScript object, string, or Buffer as the request body. When you pass a plain object to data, Playwright automatically serializes it to JSON and sets Content-Type: application/json. Options: data (auto-serialized), form (form-encoded), multipart (file uploads). There is no body, json, or payload key.
Challenge 6IntermediateHeaders
Solved
What Content-Type does Playwright set when you use data: with an object?
You pass a plain JavaScript object to data: in a POST request. What Content-Type header does Playwright set automatically?
Answer: C — application/json
When you pass a plain JavaScript object to data:, Playwright automatically: (1) serializes it with JSON.stringify(), and (2) sets Content-Type: application/json. You don't need to set it manually. If you pass a string to data:, no Content-Type is set automatically. Use form: for application/x-www-form-urlencoded, and multipart: for multipart/form-data.
Challenge 7BeginnerResponse
Solved
When would you use response.text() instead of response.json()?
A response returns HTML content, not JSON. Which method should you call to read the body?
Answer: B — response.text() for non-JSON content
response.json() attempts to parse the body as JSON and will throw if the body is not valid JSON. response.text() returns the raw body as a string — works for HTML, plain text, XML, CSV. response.body() returns a Buffer (binary data). Use the right method for the content type: JSON → .json(), text → .text(), binary → .body().
Challenge 8IntermediateAuth
Solved
How do you send a Bearer token with every API request?
You want to include an Authorization: Bearer <token> header on all requests from an APIRequestContext. What is the correct approach?
const context = await playwright.request.newContext({
  baseURL: 'https://api.example.com',
  ???: { 'Authorization': 'Bearer abc123' }
});
Answer: B — extraHTTPHeaders:
extraHTTPHeaders is the Playwright option for setting default headers on every request made by the context. Set it when creating the context (playwright.request.newContext({ extraHTTPHeaders: {...} })) or in playwright.config.ts under use: { extraHTTPHeaders: {...} }. These headers are merged with any per-request headers. Use this for auth tokens, API keys, and custom headers that apply to all requests.
Challenge 9IntermediateHTTP Methods
Solved
What is the difference between PUT and PATCH?
You want to update a user's email only, leaving all other fields unchanged. Should you use PUT or PATCH?
Answer: B — PATCH for partial updates; PUT replaces all
PUT: Replace the entire resource. If you don't include a field, it gets reset/deleted. You must send the complete representation. PATCH: Partial update — only the fields you send are changed; others remain untouched. Use PATCH when updating a single field. Use PUT when replacing the full resource. Most modern REST APIs support both, but PATCH is safer for partial updates.
Challenge 10BeginnerHTTP Status
Solved
What does 204 No Content mean and can you call response.json() on it?
A DELETE request returns status 204. What does this mean, and is it safe to call response.json()?
Answer: B — success but no body; json() will throw
204 No Content means the operation succeeded but there is no body to return. Common for DELETE, and sometimes PUT/PATCH. The HTTP spec requires no body with 204. Calling response.json() on a 204 will throw a JSON parse error because there's nothing to parse. To assert a successful DELETE: expect(response.status()).toBe(204) — that's it, no body to check.
Challenge 11IntermediateHeaders
Solved
Where does extraHTTPHeaders in playwright.config.ts apply?
You set use: { extraHTTPHeaders: { 'X-API-Key': 'secret' } } in config. Where are these headers applied?
Answer: B — all requests from pages and API contexts
extraHTTPHeaders in the use section of config applies to the browser context — which means ALL HTTP requests made by pages (browser network requests) AND all requests made via the request fixture or newContext(). This is a powerful way to inject auth tokens globally. You can override or extend per-request with individual headers in specific calls.
Challenge 12BeginnerResponse
Solved
What does response.ok() return?
What does response.ok() return, and for which status codes does it return true?
Answer: B — true for 200–299
response.ok() is a synchronous boolean convenience method — it returns true if the HTTP status code is in the 200–299 range (success family). It returns false for 400+ (client errors), 500+ (server errors), and also for 300+ (redirects). Use it as a quick pass/fail check: expect(response.ok()).toBeTruthy() instead of checking the exact status code when you only care that the request succeeded.
Challenge 13AdvancedAPI Context
Solved
How do you create a reusable APIRequestContext outside of tests?
You want to create a shared API client in a fixture or global setup. Which Playwright API creates an APIRequestContext independently?
import { chromium, ???  } from '@playwright/test';

const apiContext = await playwright.request.newContext({
  baseURL: 'https://api.example.com',
  extraHTTPHeaders: { 'Authorization': 'Bearer token' }
});
Answer: B — playwright.request.newContext()
To create a standalone APIRequestContext outside the test fixture system (e.g., in globalSetup), use playwright.request.newContext(options) where playwright is the Playwright instance imported from @playwright/test. Remember to call await apiContext.dispose() when done. Inside tests, it's easier to use the built-in request fixture which handles lifecycle automatically.
Challenge 14AdvancedAuth
Solved
Can storageState be used to reuse auth in API tests?
You logged in via the UI and saved storageState. Can you reuse that in subsequent API request contexts?
Answer: B — APIRequestContext accepts storageState
playwright.request.newContext({ storageState: 'auth.json' }) loads saved cookies and local storage into the API context. This means API requests will include session cookies from the saved auth state — allowing you to make authenticated API calls without re-logging in. This is the standard pattern for reusing browser sessions in API tests.
Challenge 15BeginnerHTTP Status
Solved
What does HTTP status 429 mean?
Your API test suddenly starts returning 429. What does this indicate?
Answer: B — 429 Too Many Requests
429 Too Many Requests means the client has sent too many requests in a given time window — the rate limit has been exceeded. The server may include a Retry-After header indicating when to try again. In API tests, 429 can occur when tests run quickly in parallel and hammer the same endpoint. Solutions: add delays between requests, use test doubles/mocks, or test against a rate-limit-free staging environment.