Introduction
In the previous chapters, we learned how to send HTTP requests and automate complete CRUD operations using Playwright. However, the APIs we tested were public and didn't require authentication.
In the real world, almost every enterprise application protects its APIs. Whether you're testing a banking application, healthcare system, e-commerce platform, or SaaS product, you'll need to authenticate before accessing protected endpoints.
This chapter will teach you how professional automation engineers handle API authentication in Playwright using reusable fixtures and enterprise best practices.
By the end of this tutorial, you'll know how to automate secured APIs without duplicating login logic across hundreds of tests.
Why Authentication Matters
Authentication verifies who you are before allowing access to protected resources. Without valid credentials, most APIs return 401 Unauthorized or 403 Forbidden.
A successful login provides some form of authentication that your application uses for future requests. This may be:
- Bearer Token
- JWT Token
- API Key
- Session Cookie
- OAuth Access Token
Your Playwright tests must send these credentials with every protected API request.
Common Authentication Types
As an automation engineer, you'll frequently encounter the following authentication mechanisms.
| Authentication | Common Usage |
| -------------------- | ------------------------------ |
| Bearer Token | REST APIs |
| JWT Token | Modern Web Applications |
| API Key | Third-party APIs |
| OAuth 2.0 | Google, Microsoft, GitHub APIs |
| Session Cookies | Web Applications |
| Basic Authentication | Internal Services |Fortunately, Playwright supports all of them.
Understanding Bearer Token Authentication
Bearer Token authentication is the most common authentication method in REST APIs. The typical authentication flow looks like this:
Login Request
│
▼
Receive Access Token
│
▼
Store Token
│
▼
Send Token in Every RequestThe server validates the token before processing your request. If the token is invalid or expired, the API rejects the request.
Example Authentication Request
Imagine your application exposes the following login endpoint:
POST /loginRequest Body:
{
"email":"admin@test.com",
"password":"Password123"
}Successful Response:
{
"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}This token will be used for every subsequent API request.
Sending Bearer Tokens
Playwright allows you to include HTTP headers when making requests.
const response = await request.get("/users",{
headers:{
Authorization:"Bearer YOUR_TOKEN"
}
});Every request now includes the authentication token. Most enterprise APIs use this approach.
Why Hardcoding Tokens Is a Bad Idea
Many beginners write code like this:
Authorization:"Bearer abc123xyz456"This is a terrible practice because:
- Tokens expire.
- Tokens change between environments.
- Tokens should never be committed to Git.
- Updating hundreds of files becomes impossible.
Instead, authenticate once and reuse the token.
Creating a Reusable Authentication Fixture
Professional Playwright frameworks avoid logging in before every test. Instead, they authenticate once and provide an already authenticated request context.
Create a new file:
tests/fixtures/auth.fixture.tsimport { test as base, expect } from "@playwright/test";
export const test = base.extend({
authenticatedRequest: async ({ playwright }, use) => {
const loginContext = await playwright.request.newContext({
baseURL: process.env.BASE_URL
});
const loginResponse = await loginContext.post("/login",{
data:{
email:process.env.USER_EMAIL,
password:process.env.USER_PASSWORD
}
});
expect(loginResponse.ok()).toBeTruthy();
const { token } = await loginResponse.json();
const authenticatedContext =
await playwright.request.newContext({
baseURL:process.env.BASE_URL,
extraHTTPHeaders:{
Authorization:`Bearer ${token}`
}
});
await use(authenticatedContext);
await authenticatedContext.dispose();
await loginContext.dispose();
}
});
export { expect };This fixture automatically performs authentication before your tests begin. Your test files no longer need to worry about login.
Using the Authentication Fixture
Your test becomes much cleaner.
import { test, expect } from "../fixtures/auth.fixture";
test("Retrieve Users", async ({ authenticatedRequest }) => {
const response =
await authenticatedRequest.get("/users");
expect(response.status()).toBe(200);
});Notice how there's no login logic inside the test. That's exactly how enterprise automation frameworks are built.
JWT Authentication
JWT stands for JSON Web Token. It is one of the most widely used authentication mechanisms in modern applications.
A JWT consists of three parts:
Header
Payload
SignatureExample:
xxxxx.yyyyy.zzzzzThe token contains information such as:
- User ID
- Username
- Role
- Expiration Time
- Permissions
Your Playwright tests usually don't need to decode the token. Simply send it in the Authorization header.
API Key Authentication
Some services authenticate using API Keys.
const response = await request.get("/weather",{
headers:{
"x-api-key":process.env.API_KEY
}
});This approach is commonly used by:
- Stripe
- Twilio
- OpenWeather
- AWS APIs
- Azure Services
Always store API keys in environment variables.
Basic Authentication
Some legacy applications still use Basic Authentication. Playwright supports it during context creation.
const context =
await playwright.request.newContext({
httpCredentials:{
username:"admin",
password:"password"
}
});Although less common today, you may still encounter it in internal enterprise systems.
Storing Credentials Securely
Never hardcode sensitive information. Instead, create a .env file.
BASE_URL=https://qa.mycompany.com
USER_EMAIL=admin@test.com
USER_PASSWORD=Password123
API_KEY=xxxxxxxxxxxxxxxxLoad environment variables during test execution. Benefits include:
- Better security
- Environment flexibility
- Easier maintenance
- CI/CD compatibility
Authentication by Environment
Enterprise applications usually have multiple environments.
Development
QA
Stage
ProductionEach environment uses different URLs, users, passwords, and tokens. Instead of changing your code, switch environments using configuration files.
.env.dev
.env.qa
.env.stage
.env.prodThis makes deployments significantly easier.
Token Expiration
Access tokens eventually expire. Your framework should automatically request a fresh token when needed. Professional automation frameworks never assume a token remains valid forever.
A common approach is:
If token expired
↓
Login Again
↓
Generate New Token
↓
Continue TestsKeeping this logic inside your fixture prevents every test from handling token expiration individually.
Best Practices
Experienced automation engineers follow these authentication practices:
- Authenticate once per worker.
- Reuse authentication across tests.
- Store credentials in environment variables.
- Never commit tokens to Git.
- Dispose request contexts after execution.
- Keep login logic inside fixtures or service classes.
Following these practices results in faster, cleaner, and more maintainable automation suites.
Common Mistakes
Avoid these common authentication mistakes:
- Hardcoding tokens.
- Logging in before every single test.
- Storing passwords inside source code.
- Using production credentials in test automation.
- Forgetting to dispose request contexts.
- Sharing mutable authentication data between parallel tests.
These issues often lead to flaky tests and difficult maintenance.
Interview Questions
Why should authentication logic be placed inside fixtures instead of test files?
Because fixtures centralize login functionality, eliminate duplicated code, improve maintainability, and ensure every test receives a clean authenticated request context.
Why should credentials be stored in environment variables?
Environment variables improve security, simplify environment switching, and prevent sensitive information from being exposed in version control.
What is the difference between Authentication and Authorization?
Authentication verifies the identity of a user. Authorization determines what that authenticated user is allowed to access.
Summary
Congratulations! You can now authenticate secured APIs using Playwright.
In this chapter, you learned:
- Bearer Token Authentication
- JWT Authentication
- API Key Authentication
- Basic Authentication
- Creating reusable authentication fixtures
- Managing environment variables
- Handling token expiration
- Enterprise authentication best practices
- Common mistakes to avoid
In the next chapter, we'll build a professional API Framework Architecture using reusable API Clients, Service Layer, Request Manager, Environment Manager, and Base API Classes—the same architecture used by enterprise SDET teams to automate hundreds of APIs efficiently.
Auth Strategy in a Real Organisation
Most teams start with a single admin token in an environment variable and discover the limits of that approach the first time a bug slips through: an endpoint returned data to a viewer that only an owner should see, and every test ran as an owner, so nothing caught it. Authorisation coverage is not a nice-to-have — for anything multi-tenant, it is the highest-risk area of the product.
The design that scales is a role-keyed token cache. A worker-scoped fixture holds a map from role name to token. The first test that asks for the editor token triggers one login; every later test on that worker reuses it. Tests then read as sentences: given an editor, when they call this endpoint, expect 403. Adding a new role is one entry in the map, not a new copy of the login helper.
Token lifetime deserves explicit thought. Access tokens that expire in five minutes will die mid-run on a sharded pipeline. Store the expiry alongside the token and refresh when there is less than a minute left, rather than assuming a run finishes before the clock does. And never log the token — Playwright traces are attached to CI artifacts, and a leaked staging token is still a leaked credential.
Common Mistakes
- Committing a .env file with real credentials. Use .env.example in the repo and inject real values as CI secrets.
- Logging in inside beforeEach. That is one login per test — slow, and often enough to trip the auth provider's rate limit.
- Only testing the happy path of auth. Expired token, malformed token, missing header, and wrong-tenant token are four cheap tests that catch real vulnerabilities.
- Hardcoding the Bearer prefix in twelve places instead of building the header once in the fixture.
Frequently Asked Questions
Bearer token or API key — which should my tests use?
Use whatever real clients use. If production consumers send an API key, testing with a bearer token means you never exercise the code path your customers hit.
How do I test OAuth flows that require a browser?
Run the interactive consent once with a browser context, save storageState, and reuse the resulting refresh token in API tests. Do not automate the consent screen on every run.
Can I share one token across all workers?
Yes, via globalSetup writing to a file that workers read. It is faster, but it couples workers together — only do it when your auth provider rate-limits aggressively.
Complete professional Playwright + TypeScript enterprise framework
Production-grade architecture, fixtures, reporters and CI/CD — ready to run.
Get Playwright tutorials in your inbox
Weekly tips, real-world examples, and framework patterns – no spam, unsubscribe anytime.
Playwright Framework Series
View all →- 1Getting Started with Playwright: Installation, Setup, and Your First Test
- 2Playwright Locators: The Complete Guide with Real-World Examples
- 3Playwright Actions: Complete Guide to Click, Fill, Hover, Keyboard, Mouse & File Upload
- 4Playwright Assertions Complete Guide: Web-First Assertions, Auto-Retry & Custom Matchers
- 5Playwright Auto Waiting: The Complete Guide with Real-World Examples
- 6Playwright Fixtures: The Complete Guide with Real-World Examples
- 7Playwright Browser Context & Multiple Tabs: The Complete Guide with Real-World Examples
- 8Playwright Authentication & Session Management: Complete Guide with Enterprise Examples
- 9Playwright Network Interception & API Mocking: Complete Guide with Real-World Examples
- 10Playwright Page Object Model (POM): The Complete Guide with Enterprise Examples
- 11Page Object Model with Playwright: A Practical Guide
- 12How to Build a Robust Professional Playwright Framework from Scratch (Step-by-Step)
- 13Building an Enterprise Playwright Framework from Scratch
API Testing Series
View all →- 1Part 1 : Playwright API Testing Tutorial: Build Enterprise-Level API Automation Framework
- 2Part 2: Playwright API Testing Tutorial: Setting Up Project & Sending Your First API Request
- 3Part 3: Mastering CRUD Operations in Playwright API Testing
- 4Part 4: Authentication in Playwright API Testing (Bearer Token, JWT, API Key & Reusable Fixtures)
- 5Part 5: Building an Enterprise-Level Playwright API Automation Framework
- 6Part 6: API Models, Schema Validation & Test Data Management in Playwright
- 7Part 7: Custom Fixtures, Hooks, Logging & Parallel Execution in Playwright API Testing
- 8Part 8: Building a Production-Ready Playwright API Framework (Environment Management, CI/CD, Reporting & Best Practices)
- 9Part 9: Advanced Playwright API Testing Techniques for Enterprise Automation
- 10Part 10: Building a Complete Enterprise Playwright API Automation Framework (Final Part)
- 11Playwright Backend Testing Tutorial – REST API, GraphQL, WebSocket, Kafka, Database & Microservices