--- comments: true --- # PaddleOCR.js (browser deployment) PaddleOCR provides **PaddleOCR.js**, a browser OCR SDK for running the PP-OCR pipeline in the browser. You can embed text detection and recognition in web apps and run inference on the client. The npm package is **`@paddleocr/paddleocr-js`**. Source and demo live under [`paddleocr-js`](https://github.com/PaddlePaddle/PaddleOCR/tree/{{PADDLEOCR_GITHUB_REF}}/paddleocr-js) on GitHub. ## Install ```bash npm install @paddleocr/paddleocr-js ``` ## Quick start ```js import { PaddleOCR } from "@paddleocr/paddleocr-js"; const ocr = await PaddleOCR.create({ lang: "ch", ocrVersion: "PP-OCRv5", ortOptions: { backend: "auto" } }); const [result] = await ocr.predict(fileOrBlob); console.log(result.items); ``` `predict` resolves to an **array** of `OcrResult` (one per input image). A single `Blob` / `File` still produces a one-element array—use destructuring or `results[0]`. ## Construction options Two styles: **direct parameters** to `PaddleOCR.create({ ... })`, or a **`pipelineConfig`** object. ### 1. Direct parameters With direct parameters, you can specify models and set batch sizes, ORT options, and other runtime settings. **Model selection — `lang` + `ocrVersion`:** ```js await PaddleOCR.create({ lang: "ch", ocrVersion: "PP-OCRv5" }); ``` **Model selection — built-in model names:** ```js await PaddleOCR.create({ textDetectionModelName: "PP-OCRv5_mobile_det", textRecognitionModelName: "PP-OCRv5_mobile_rec" }); ``` **Custom models** — provide a name and asset URL for each of detection and recognition: ```js await PaddleOCR.create({ textDetectionModelName: "my_det_model", textDetectionModelAsset: { url: "https://example.com/models/my_det_model.tar" }, textRecognitionModelName: "my_rec_model", textRecognitionModelAsset: { url: "https://example.com/models/my_rec_model.tar" } }); ``` **Batch sizes, ORT options, and other runtime settings:** ```js await PaddleOCR.create({ lang: "ch", ocrVersion: "PP-OCRv5", textDetectionBatchSize: 2, textRecognitionBatchSize: 8, ortOptions: { backend: "wasm", wasmPaths: "/assets/" } }); ``` #### Custom model archive format and validation The SDK downloads `textDetectionModelAsset.url` / `textRecognitionModelAsset.url` over HTTP(S) and parses the body as a **plain ustar tar (uncompressed)** archive. Ensure that: | Requirement | Details | |-------------|---------| | Archive format | The response body must be an **uncompressed `.tar`**. The implementation does **not** gunzip **`.tar.gz`**; if you pass a gzip-compressed tarball, parsing will typically fail and an error will be thrown. | | Required files | The tar must contain **`inference.onnx`** and **`inference.yml`** (they may live in a subdirectory; entries are matched by basename). | | `model_name` | **`inference.yml`** must define a **`model_name`** that matches the `textDetectionModelName` / `textRecognitionModelName` you pass to `create`. This is checked after load during initialization. | If you need to convert Paddle models into the ONNX model files used here, see [Obtaining ONNX models](../others/obtaining_onnx_models.en.md). The standard model files produced by that workflow can then be packaged as a `.tar` following the rules above for use with PaddleOCR.js. If the archive or model files do not meet these rules, initialization typically fails with an **`Error`** that describes the problem, for example: non-2xx download, missing `inference.onnx` / `inference.yml` in the tar, empty resources, missing or mismatched `model_name`, incomplete model config, or ONNX load failure. There is no silent fallback. All selected OCR models must satisfy the `model_name` rules above. ### 2. Pipeline config ```js import { PaddleOCR } from "@paddleocr/paddleocr-js"; const pipelineConfig = ` pipeline_name: OCR SubModules: TextDetection: model_name: PP-OCRv5_mobile_det batch_size: 2 TextRecognition: model_name: PP-OCRv5_mobile_rec batch_size: 6 `; const ocr = await PaddleOCR.create({ pipelineConfig }); ``` `pipelineConfig` can be YAML text or a parsed object. In the browser, submodule `model_dir` must be **`null` or an asset object** (e.g. `{ url: "..." }`), not a local filesystem path string. If you want to start from a pipeline configuration exported by PaddleOCR / PaddleX, see the "Exporting Pipeline Configuration Files" section in [PaddleOCR and PaddleX](../../paddleocr_and_paddlex.en.md); the exported YAML can be used as the basis for `pipelineConfig`, and any `model_dir` entries should then be adapted to browser-side asset objects. If both direct parameters and `pipelineConfig` are provided, **direct parameters take precedence**. ## Prediction ### Params `ocr.predict(image | images[], params?)` accepts both camelCase and PaddleOCR-style snake_case: - `textDetLimitSideLen` or `text_det_limit_side_len` - `textDetLimitType` or `text_det_limit_type` - `textDetMaxSideLimit` or `text_det_max_side_limit` - `textDetThresh` or `text_det_thresh` - `textDetBoxThresh` or `text_det_box_thresh` - `textDetUnclipRatio` or `text_det_unclip_ratio` - `textRecScoreThresh` or `text_rec_score_thresh` Supported `image` inputs include `Blob`, `ImageBitmap`, `ImageData`, `HTMLCanvasElement`, `HTMLImageElement`, and `cv.Mat`. Pass an array to run on multiple images in one call. In **worker mode**, `cv.Mat` is not transferable and is not supported as input. ### Return value Resolves to `Promise`. Each `OcrResult` contains: - `image`: `{ width, height }` for that source - `items`: recognized lines (`poly`, `text`, `score`) - `metrics`: `detMs`, `recMs`, `totalMs`, `detectedBoxes`, `recognizedCount` — box and line counts are per image; `detMs`, `recMs`, and `totalMs` cover the **entire** `predict()` call (identical on every element when you pass multiple images) - `runtime`: requested backend and provider metadata ## Worker mode You can run the pipeline inside a dedicated Worker while keeping the same high-level API: ```js import { PaddleOCR } from "@paddleocr/paddleocr-js"; const ocr = await PaddleOCR.create({ lang: "ch", ocrVersion: "PP-OCRv5", worker: true, ortOptions: { backend: "wasm", wasmPaths: "https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/", numThreads: 2, simd: true } }); ``` Summary: - Worker mode uses the package worker entry, not ONNX Runtime Web `env.wasm.proxy` - When `worker: true`, the package forces ORT wasm proxy off to avoid nested workers - Browser inputs are normalized on the main thread, then transferred to the worker - `cv.Mat` is only supported on the main-thread pipeline path ## Visualization The optional **`@paddleocr/paddleocr-js/viz`** subpath renders OCR results to images. ```js import { OcrVisualizer } from "@paddleocr/paddleocr-js/viz"; const viz = new OcrVisualizer({ font: { family: "Noto Sans SC", source: "/fonts/NotoSansSC-Regular.ttf" } }); const blob = await viz.toBlob(imageBitmap, result); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = "ocr_result.png"; a.click(); URL.revokeObjectURL(url); viz.dispose(); ``` `renderOcrToBlob` and `deterministicColor` are also exported. Visualization takes a **single** `OcrResult` (for one image, use the first element of the `predict` result array). ## API summary - `PaddleOCR.create(options)` - `ocr.initialize()` / `ocr.getInitializationSummary()` - `ocr.predict(image | images[], params?)` → `Promise` - `ocr.dispose()` - `parseOcrPipelineConfigText(text)` / `normalizeOcrPipelineConfig(config)` - `OcrVisualizer`, `renderOcrToBlob`, `deterministicColor` (from `@paddleocr/paddleocr-js/viz`) ## Host application responsibilities The SDK manages OpenCV.js and ONNX Runtime internally. You still handle: - **COOP/COEP** (and related headers) when enabling threaded WASM or WebGPU - **ORT environment options** (e.g. `wasmPaths`, threads, SIMD) - A bundler/runtime that can emit and load **module workers** when `worker: true`