CTCaliberTek
Course: Playwright with TypeScript: End to End · Lesson 5 of 9Log in to track your progress and earn a certificate when you finish the course.
Software Testing

Playwright API Testing and Reusing Authentication

Published August 23, 2026·Updated October 29, 2026·9 min read
Like SaveLog in to like, save, and track progress.

Introduction

Playwright is not limited to the browser. Its request fixture sends HTTP calls, so you can test APIs directly or prepare test data quickly. You can also sign in once and reuse that saved session in every test, which saves a lot of time. This lesson covers both.

Prerequisites

  • Playwright fixtures and configuration basics
  • A basic understanding of REST and HTTP status codes

Step-by-Step Guide

Step 1: Send API requests

The request fixture exposes get, post, put, and delete. Check the response with expect and read JSON with response.json().

import { test, expect } from '@playwright/test';

test('GET a post', async ({ request }) => {
  const response = await request.get('https://jsonplaceholder.typicode.com/posts/1');
  expect(response.ok()).toBeTruthy();

  const body = await response.json();
  expect(body.id).toBe(1);
});

Step 2: Create data with POST

Pass a data object and Playwright sends it as JSON. Assert on the status code your API documents.

test('POST a post', async ({ request }) => {
  const response = await request.post('https://jsonplaceholder.typicode.com/posts', {
    data: { title: 'CaliberTek', body: 'Hello', userId: 1 },
  });
  expect(response.status()).toBe(201);
});

Step 3: Combine API setup with UI checks

Use the API to create the data a test needs, then verify it in the browser. This is much faster and more reliable than building state by clicking through the UI.

Step 4: Write a setup test that signs in once

A setup test logs in through the UI and saves cookies and local storage to a file. Read credentials from environment variables rather than hard-coding them.

// tests/auth.setup.ts
import { test as setup } from '@playwright/test';
import path from 'path';

const authFile = path.join(__dirname, '../playwright/.auth/user.json');

setup('authenticate', async ({ page }) => {
  await page.goto('https://example.com/login');
  await page.getByLabel('Username').fill(process.env.APP_USER!);
  await page.getByLabel('Password').fill(process.env.APP_PASSWORD!);
  await page.getByRole('button', { name: 'Sign in' }).click();
  await page.waitForURL('**/dashboard');

  await page.context().storageState({ path: authFile });
});

Step 5: Reuse the session in your projects

Create a setup project and make the browser project depend on it. Every test then starts already signed in. Add the auth folder to .gitignore so session files are never committed.

// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  projects: [
    { name: 'setup', testMatch: /.*\.setup\.ts/ },
    {
      name: 'chromium',
      use: {
        ...devices['Desktop Chrome'],
        storageState: 'playwright/.auth/user.json',
      },
      dependencies: ['setup'],
    },
  ],
});

FAQs

Does storageState save everything about a session?
It saves cookies and local storage. Data kept only in sessionStorage is not included, so apps that store tokens there need extra handling.
Why test the API separately from the UI?
API tests run in milliseconds and pinpoint backend problems without browser noise. Reserve UI tests for behavior that really needs a browser.

Summary

Use the request fixture for fast API checks and data setup, and save an authenticated session once so every UI test can skip the login. Keep credentials in environment variables and session files out of Git.

Related tutorials

Comments

Log in or create a free account to join the discussion.

  • No comments yet. Be the first to comment.