Every Playwright project is controlled by one file: playwright.config.ts. In this lesson you will learn what each important option does, how projects work, and how to build a clean, production-ready config step by step.
📖 What You’ll Learn: test runner options (testDir, timeout, workers, retries, reporter), the use block (baseURL, headless, viewport, screenshot, video, trace, timeouts), projects for browsers and devices, setup projects, webServer, test.use overrides and a complete annotated config.
📄 What Is playwright.config.ts?
playwright.config.ts is the control centre of your Playwright project. It sits in the project root and tells Playwright where your tests are, how to run them, which browsers to use, and what to record when something fails. Because it is a TypeScript file wrapped in defineConfig(), your editor autocompletes every option and flags typos.
Here is the config the installer generates (comments shortened):
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: 'html',
use: {
// baseURL: 'http://localhost:3000',
trace: 'on-first-retry',
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
{ name: 'webkit', use: { ...devices['Desktop Safari'] } },
],
});
The options fall into three groups: test runner options (top level), browser and context options (inside use), and projects (named variations of use). Let’s go through each.
⚙️ Test Runner Options (Top Level)
| Option | What it does | Example |
|---|---|---|
testDir | Folder that contains your tests | './tests' |
testMatch / testIgnore | Which files count as tests (default: *.spec.ts and *.test.ts) | '**/*.e2e.ts' |
timeout | Max time for one test, default 30 seconds | 60_000 |
expect.timeout | Max time for one assertion, default 5 seconds | { timeout: 10_000 } |
fullyParallel | Run tests inside a file in parallel too | true |
workers | Number of parallel worker processes | 4 or '50%' |
retries | Re-run failed tests this many times | 2 |
forbidOnly | Fail the run if test.only was left in code (great for CI) | !!process.env.CI |
maxFailures | Stop the run after N failures | 10 |
reporter | How results are reported | 'html', 'list', or an array |
outputDir | Where screenshots, videos and traces are saved | 'test-results' |
globalSetup / globalTeardown | Files that run once before / after all tests | './global-setup.ts' |
💡 Tip: process.env.CI is set automatically by most CI systems (including GitHub Actions). The default config uses it to apply stricter settings in CI and faster ones locally.
🌐 The use Block: Browser and Context Options
Everything inside use applies to the browser, context and page that each test receives.
| Option | What it does |
|---|---|
baseURL | Lets you write page.goto('/login') instead of the full URL |
headless | false shows the browser window (default true) |
viewport | Browser window size, e.g. { width: 1280, height: 720 } |
screenshot | 'off', 'on' or 'only-on-failure' |
video | 'off', 'on', 'retain-on-failure' or 'on-first-retry' |
trace | 'off', 'on', 'retain-on-failure' or 'on-first-retry' |
actionTimeout | Max time for each click, fill etc. (default: no separate limit) |
navigationTimeout | Max time for goto and navigations |
ignoreHTTPSErrors | Accept invalid certificates on test environments |
locale / timezoneId | Test in another language or time zone, e.g. 'en-IN', 'Asia/Kolkata' |
storageState | Start each test already logged in (see save login session) |
testIdAttribute | Custom attribute for getByTestId, e.g. 'data-test' |
launchOptions | Low-level options such as { slowMo: 500 } to slow down actions |
A practical use block for most projects:
use: {
baseURL: process.env.BASE_URL ?? 'https://www.saucedemo.com',
headless: true,
viewport: { width: 1366, height: 768 },
screenshot: 'only-on-failure',
video: 'retain-on-failure',
trace: 'on-first-retry',
actionTimeout: 15_000,
testIdAttribute: 'data-test',
},
🧭 Projects: Browsers, Devices and Environments
A project is a named group of settings. Every test runs once per project. Projects are how you run cross-browser tests, mobile emulation, or different environments.
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
{ name: 'webkit', use: { ...devices['Desktop Safari'] } },
// Branded browsers
{ name: 'Google Chrome', use: { ...devices['Desktop Chrome'], channel: 'chrome' } },
{ name: 'Microsoft Edge', use: { ...devices['Desktop Edge'], channel: 'msedge' } },
// Mobile emulation
{ name: 'Mobile Safari', use: { ...devices['iPhone 13'] } },
{ name: 'Mobile Chrome', use: { ...devices['Pixel 5'] } },
],
Run a single project with npx playwright test --project=chromium.
Setup project: log in once for all tests
Projects can depend on each other. A common pattern is a setup project that logs in and saves the session, which other projects reuse:
projects: [
{ name: 'setup', testMatch: /.*\.setup\.ts/ },
{
name: 'chromium',
use: { ...devices['Desktop Chrome'], storageState: 'playwright/.auth/user.json' },
dependencies: ['setup'],
},
],
🚀 webServer: Start Your App Before Testing
If you test your own application locally, Playwright can start it for you and wait until it is ready:
webServer: {
command: 'npm run start',
url: 'http://localhost:3000',
reuseExistingServer: !process.env.CI,
timeout: 120_000,
},
📋 A Complete, Annotated Config for This Course
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
timeout: 30_000,
expect: { timeout: 7_000 },
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 2 : undefined,
reporter: [
['list'], // readable terminal output
['html', { open: 'never' }], // HTML report in playwright-report/
],
use: {
baseURL: process.env.BASE_URL ?? 'https://www.saucedemo.com',
testIdAttribute: 'data-test',
screenshot: 'only-on-failure',
video: 'retain-on-failure',
trace: 'on-first-retry',
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
],
});
📝 Note: You can keep several config files (for example one for API tests and one for UI tests) and choose one with --config. See multiple config files, and load secrets from a .env file as shown in environment variables with .env.
🎯 Override Config for One File or Test
Settings in the config are defaults. You can override use options for a file or a describe block with test.use():
import { test, expect } from '@playwright/test';
test.use({ viewport: { width: 390, height: 844 }, locale: 'hi-IN' });
test('mobile layout in Hindi locale', async ({ page }) => {
await page.goto('/');
// ...
});
And change the timeout of a single test with test.setTimeout(60_000) or test.slow().
📝 Assignment
- Set
baseURLtohttps://www.saucedemo.comand update your login test to usepage.goto('/'). - Change the reporter to show
listoutput in the terminal and generate the HTML report. - Enable screenshots and videos only for failed tests. Break a test on purpose and find the screenshot and video in the HTML report.
- Add a Mobile Chrome project using
devices['Pixel 5']and run only that project. - Set
retries: 1locally, make a test fail, and observe the retry and the trace in the report. - Bonus: set
testIdAttribute: 'data-test'and replace one locator withpage.getByTestId('login-button').
❓ FAQ
🤔 Where is the Playwright config file?
In the project root, named playwright.config.ts (or .js). Playwright finds it automatically; use --config path/to/file.ts to choose another.
🤔 How do I increase the timeout in Playwright?
Set timeout for whole tests and expect: { timeout } for assertions in the config, or call test.setTimeout() in a single test. See Playwright waits for all timeouts.
🤔 How do I run Playwright tests in headed mode by default?
Set use: { headless: false } in the config, or pass --headed on the command line.
🤔 What does workers mean in the Playwright config?
Workers are parallel processes that run tests. workers: 4 runs up to four test files at the same time; undefined lets Playwright use about half of your CPU cores.
🤔 What is the difference between use and projects?
use sets default browser and context options for all tests. Each project adds a name and its own use settings on top, and every test runs once per project.
🎬 Watch the full Playwright tutorial series on YouTube!
Subscribe to SqaToolsByDY • Practice on sqatools.in
8 thoughts on “playwright.config.ts Explained: Every Important Playwright Config Option”