ScreenshotNeo

BlogGuides

Playwright Tags: How to Organize and Run Tagged Tests

Tag Playwright tests with clear labels, then use grep filters and projects to run the right subset locally or in CI.

By the ScreenshotNeo team4 October 20267 min read

Playwright tags are labels attached to tests or test groups. Add them with a test details object or an @ token in the title, then select tests with --grep or exclude them with --grep-invert. Use tags for categories that cut across your suite, such as smoke tests or checkout tests; use projects for configured execution groups such as browsers or environments.

Tags must start with @. Playwright displays them in reports, and its grep filter searches a combined identity string that includes the project name, file name, describe title, test title, and tags. That means grep can match ordinary text too, not just explicit tags. See the official tag guide, Test API, and command-line reference.

1. Add tags to tests

The details-object form keeps classification out of the human-readable test title. This is a complete example test file:

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

test('checkout accepts a valid card', {
  tag: ['@smoke', '@critical'],
}, async ({ page }) => {
  await page.goto('https://example.com/checkout');
  await expect(page.getByRole('heading', { name: /checkout/i })).toBeVisible();
});

Replace the example URL and assertion with your application’s checkout page and expected behavior. You can also put the tag token in the title:

test('checkout accepts a valid card @smoke', async ({ page }) => {
  await page.goto('https://example.com/checkout');
  await expect(page.getByRole('heading', { name: /checkout/i })).toBeVisible();
});

A tag on a describe group applies to tests in that group. Individual tests can add more tags:

test.describe('checkout', { tag: '@checkout' }, () => {
  test('accepts a valid card', { tag: ['@smoke', '@critical'] }, async ({ page }) => {
    await page.goto('https://example.com/checkout');
    await expect(page.getByRole('heading', { name: /checkout/i })).toBeVisible();
  });

  test('shows a declined-card message', { tag: '@regression' }, async ({ page }) => {
    await page.goto('https://example.com/checkout');
    // Add the declined-card setup and assertion for your application.
  });
});

Pick a tag scheme that reflects decisions your team makes. For example, @smoke and @regression can describe execution purpose, @slow can identify tests that take longer, and @checkout can describe a product area. These are practical naming suggestions, not a prescribed Playwright taxonomy. Agree on spelling and meaning, then apply a shared label at the describe boundary when every test in that group belongs to it.

2. Run tests by tag from the command line

Run commands from the project root where the Playwright test configuration and package are available:

# Include tests matching one tag
npx playwright test --grep @smoke

# Exclude tests matching a tag
npx playwright test --grep-invert @slow

# Include tests matching either tag (regular-expression OR)
npx playwright test --grep "@smoke|@critical"

# Include tests containing both tags (regular-expression lookaheads)
npx playwright test --grep "(?=.*@smoke)(?=.*@critical)"

--grep and --grep-invert take regular-expression patterns. The OR pipe and AND lookaheads above are regex syntax; they are not separate Playwright operators. Quote patterns with shell-significant characters, especially the pipe and parentheses. PowerShell has its own argument parsing rules; follow Playwright’s shell-specific examples in the tag documentation if a pattern is changed or interpreted unexpectedly.

Other useful command combinations include restricting a tag selection to a project, or to a file:

# Smoke tests in one configured project
npx playwright test --project=chromium --grep @smoke

# Regression-tagged tests from one file
npx playwright test tests/checkout.spec.ts --grep @regression

Use npx playwright test --list --grep @smoke to inspect the selected tests without running them. Use npx playwright test --help to see the CLI options available in the Playwright version installed in your project.

3. Set a filter in Playwright configuration

For a deliberate default selection, set grep or grepInvert in playwright.config.ts. The following keeps the smoke filter scoped to one project:

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

export default defineConfig({
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
      grep: /@smoke/,
      // To exclude a tag in this project instead, use:
      // grepInvert: /@slow/,
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },
  ],
});

Configuration grep accepts a regular expression or an array of regular expressions. An array acts as alternative patterns: a test matching any pattern can be selected. The config also supports grepInvert for exclusion. A project can have its own filter, which is useful when selection policy differs by project. Check the official TestConfig reference and projects guide for the exact options.

A config-level filter changes what an ordinary test run selects. If most runs should include the full suite, keep selection on the command line instead, or make the filtered config choice explicit to the team and CI jobs.

4. Choose between tags and projects

Use Answers Selection example
Tag Which cross-cutting category does this test belong to? --grep @smoke
Project Under which shared configuration should this test run? --project=chromium
Both Which category, within which configured execution group? --project=chromium --grep @smoke

Projects commonly define browser, device, or environment configurations. Tags classify tests across those configurations. A test tagged @smoke can be selected in more than one project; a project represents how a group runs rather than a test category. See Playwright projects.

5. Add a run-level tag when useful

The configuration tag option labels every test in that configured run, which can help identify run context in reports. It does not select tests. Each configured tag must start with @.

import { defineConfig } from '@playwright/test';

export default defineConfig({
  tag: '@staging',
});

Keep this separate from test-level tags: use grep and grepInvert to choose a test subset. The run-level option is documented in the TestConfig API.

6. Organize tags so filters stay understandable

  • Use stable, specific names. A team-wide @smoke definition should mean the same thing in every folder and project.
  • Keep one label per useful dimension. A test may have several tags, such as @checkout and @smoke, when each helps answer a different selection question.
  • Tag groups only when the whole group qualifies. Place the tag on individual tests if only some members qualify.
  • Review filters with --list. This catches unexpected selection before a long run or CI change.
  • Use distinctive patterns. Since grep searches titles, paths, project names, and tags together, a generic pattern may match text that was not intended as a tag.

Playwright does not prescribe a universal naming scheme or a maximum number of tags. Keep the scheme small enough that a teammate can predict what a filter selects.

Or skip the browser setup

If you need screenshots of pages while documenting or debugging tagged browser runs, ScreenshotNeo is a website screenshot API and MCP server from ScreenshotNeo. One GET request captures a URL without setting up a browser locally. See the ScreenshotNeo API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://playwright.dev -o shot.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://playwright.dev"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://playwright.dev',
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await require('node:fs/promises').writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

ScreenshotNeo removes cookie banners, popups, and chat widgets before capture. Bot checks, blank pages, failed loads, and cache hits are never billed. Its MCP server lets AI agents use screenshot tools, and 1,000 screenshots per month are free with no card; paid plans start at $5 for 3,000. Sign up for 1,000 free screenshots a month, with no card.

Troubleshooting

Symptom Cause Fix
The tag filter selects no tests The tag is missing, misspelled, or lacks the required @ prefix; a config filter may also narrow selection. Check test and group declarations, then inspect the selection with npx playwright test --list --grep @smoke. Review config and project grep settings.
The filter selects tests with no matching tag Grep checks the combined project, file, group, title, and tag identity string. Use a more distinctive pattern and search filenames, describe titles, test titles, and project names for the matching text.
A test title contains the tag but report grouping looks awkward The tag was included as title text. Use the test details object’s tag field to keep classification separate from the display title.
Tests appear in an unexpected browser or environment A tag filter selects tests; it does not define their execution configuration. Use --project or adjust project configuration, then combine with grep if needed.
OR or AND selection behaves unexpectedly The expression is a regular expression, or the shell altered special characters. Quote the pattern, inspect it with --list, and consult the shell-specific command in the Playwright tag guide.
Normal runs unexpectedly execute only a subset A grep or grepInvert default is set in configuration. Remove the config filter or make it intentional per project; pass a CLI filter only for selected runs.

Performance, reliability, and cost

Tags do not make selected tests faster individually; they let you run fewer tests when a subset is appropriate. Run smoke coverage for quick feedback and broader coverage on the cadence your team needs. Confirm that the filter selects the intended set, since an overly broad grep can erase the time savings and an overly narrow one can omit coverage. The actual runtime depends on the selected tests, project configurations, and your execution environment.

For reliable CI behavior, keep tag meanings consistent, keep selection commands visible in scripts, and review selection changes with --list. Tags and grep are Playwright Test features; no separate service or per-tag charge is involved.

FAQ

Can one Playwright test have multiple tags?

Yes. Provide an array in the details object, and combine filters with an OR pattern or lookaheads when you need either or both labels.

Can I filter tags from the HTML report?

Tags are shown in reports, but test selection for execution is done through grep options or configuration filters. Use --grep to choose the run.

Does a describe-level tag replace tags on its tests?

No. A describe group can apply a shared tag while an individual test adds its own tags.

Should I use tags for Chromium and Firefox?

Use projects for browser configurations and tags for cross-cutting test categories. Combine project selection and a tag filter when both constraints matter.

Official references: Annotations and tags, Test API, TestConfig, Command line, and Projects.