Unmodified Tesseract, running in a browser or Node.js worker
Tesseract.js runs the Tesseract OCR engine, compiled to WebAssembly, in a browser web worker or a Node.js worker thread. Hand it a PNG, JPEG, WebP, BMP, PBM or non-animated GIF and it returns the recognized text. The engine itself is left untouched: with the same settings, language data and version, the output should match the tesseract command line. Anything that runs JavaScript and WebAssembly can use it, except React Native, which lacks WebAssembly.
The comparison of open source OCR tools sets Tesseract.js against vision models and document-to-Markdown converters.
Recognition stays on the user's device
- Images stay on the device: in a web app, recognition runs in the user's browser, with no OCR server to host.
- Tesseract parameters pass straight through:
tessedit_char_whitelistrestricts recognition to a set of characters, and therectangleoption restricts it to one region of the image. - Coordinates for every word: the
blocksoutput is a JSON tree from blocks down to single characters, with a bounding box and a confidence score at each level. hOCR, TSV and a PDF of the image with a text layer are also available. - Reusable workers: a worker loads its languages once, then processes images one after another. A scheduler spreads jobs across several workers running in parallel.
- Languages on demand: only the requested languages are downloaded (2.9 MB compressed for English, 0.7 MB for French), then cached, in IndexedDB when running in the browser.
Printed text at decent resolution, PDFs out of scope
No PDF input, no model changes. The README puts both out of scope. For a PDF, the FAQ suggests rendering each page to an image with PDF.js or muPDF, then recognizing that image. For both needs the README points to Scribe.js, which is AGPL-3.0 with a proprietary license on request; Tesseract.js is Apache-2.0.
Layout is not rebuilt. By default Tesseract.js reads the image as a single block of text (page segmentation mode 6), while the tesseract CLI segments the page automatically (mode 3), so the two can return different text for the same page until tessedit_pageseg_mode matches. Output stops at positioned text (blocks, lines, words) and includes neither Markdown nor table cells. PaddleOCR returns Markdown or JSON, tables and formulas included. Pulling fields out of a document takes another stage: Receipt OCR keeps Tesseract for raw text and hands receipt-to-JSON extraction to an LLM.
Printed text, at a decent resolution. The FAQ says handwriting is not supported, and the API docs recommend upscaling a small image before recognition.
jsDelivr by default. Out of the box, the browser fetches the worker script, the WebAssembly core and the language data from that CDN; in Node.js, the language data comes from there too. An offline app has to host those files and set workerPath, corePath and langPath. The local installation page lists four core variants, while the v7 code can load six.
Workers need recycling on a server. A WebAssembly worker's memory only grows, and the worker adds the words it meets to its internal dictionary. For a long-running Node.js server, the docs recommend recreating workers and schedulers every so often, for example every 500 jobs.
Roughly one major version a year. v4 shipped in November 2022, v5 in September 2023, v6 in January 2025 and v7 on December 15, 2025. v7 requires Node.js 16 and, per its release notes, cuts recognition time by 15 to 35% compared with v6, depending on the device. v6 removed worker.loadLanguage, so code written for v4 no longer runs as is. Since v7 the main branch has received a single commit (May 2026), and the npm package was downloaded 3.9 million times in the week of September 28, 2026.
