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.
Expected to find text "[Total: $14.00]" but OCR read "[Total: €14.00]" (Confidence: 96%)
Diff: Total: [$]14.00 → Total: [€]14.00Install and set up
npm install --save-dev @freetextfromimage/rendercheckRequires 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.
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.
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.
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.