Skip to main content

Playwright OCR testing

Assert the text users actually see on screen, not just what is in the DOM, with one extra matcher on Playwright's own expect.

A DOM assertion reads the page's markup. It cannot tell you what a user sees. A € that should be a $, text covered by another element, or text so faint nobody can read it all pass a DOM check. RenderCheck screenshots the page, reads it with OCR on your machine, and fails the test when the rendered text is wrong. Nothing is uploaded and no API key is needed.

Failure messagetext
Expected to find text "[Total: $14.00]" but OCR read "[Total: €14.00]" (Confidence: 96%)
  Diff: Total: [$]14.00  →  Total: [€]14.00

Install and set up

Terminalbash
npm install --save-dev @freetextfromimage/rendercheck

Requires Node 18+. The English OCR data ships in the package.

Import expect from RenderCheck

It is Playwright's own expect with toShowText added, so existing assertions keep working.

checkout.spec.tstypescript
import { test } from '@playwright/test';
import { expect } from '@freetextfromimage/rendercheck/playwright';

Assertions

Check text on a page or an element

toShowText retries until it passes or the timeout (default 5000 ms) runs out, like Playwright assertions.

checkout.spec.tstypescript
test('checkout shows the right total', async ({ page }) => {
  await page.goto('/checkout');

  await expect(page).toShowText('Total: $14.00', {
    minConfidence: 85,      // OCR confidence of the matched words (default 80)
    minContrastRatio: 4.5,  // WCAG contrast of the matched words (off unless set)
  });

  // One element: also compared with its DOM text.
  await expect(page.locator('#total')).toShowText('Total: $14.00');

  await expect(page).not.toShowText('Total: €14.00');
});

Prices and dates in the right locale

The expected text comes from Intl, so separators, symbol position and date order are applied for you.

locale.spec.tstypescript
await expect(page).toShowCurrency(1234.5, { currency: 'EUR', locale: 'de-DE' }); // "1.234,50 €"
await expect(page).toShowDate('2026-03-04', { locale: 'en-GB' });               // "04/03/2026"

Full option list: developer reference.

Things to know

  • Already using expect.extend? Import toShowText from the same path and add it yourself.
  • Pass region to check part of the screenshot, and fullPage: true to capture the whole scrollable page.
  • Only English OCR data ships in the package. For other scripts, download the .traineddata file and set langPath.
  • OCR is probabilistic. Set minConfidence to a level that suits your fonts, and keep text large enough to read.
  • The SDK is in developer beta and has no public adoption numbers yet.

FAQ

Does Playwright OCR testing send screenshots anywhere?

No. OCR runs in your Node process using Tesseract.js (WebAssembly). There is no API key and no network call.

How is this different from a DOM assertion like toHaveText?

toHaveText reads the markup. toShowText reads the rendered pixels, so it fails when text is covered, clipped, the wrong symbol, or too low in contrast to read.

Does it work in CI?

Yes. There are no native modules (PNG and JPEG decoding is pure JavaScript), and it needs Node 18+ and @playwright/test 1.40 or newer.

Can it replace visual regression tools?

No. It checks that specific text is visible and legible, not that the whole page looks the same as a baseline. Use it alongside snapshot tools.