Language / 言語
Home Features Install Documentation About GitHub

At a glance

  • Latest release: PaddleOCR 3.7.0 (June 11, 2026), Apache-2.0.
  • Install: PaddlePaddle first, then pip install "paddleocr[all]". For NVIDIA GPUs use the PaddlePaddle CUDA index, not PyPI.
  • Use: PaddleOCR for text lines, PPStructureV3 for Markdown/JSON, PaddleOCRVL for the most accurate document parsing on GPU.
  • 2.x code broke? use_gpu became device, ocr() became predict(). See migration.

Overview: what PaddleOCR is and which pipeline to use

PaddleOCR is an open-source OCR and document-parsing toolkit from Baidu's PaddlePaddle team, released under the Apache License 2.0. This page is a practical guide to the current 3.7 API. Every code sample on it was written against the 3.x API, and the install, API and CLI facts were checked against the official docs and the released packages on the date shown below.

Pick the pipeline by the output you need:

You needUsePython classTypical hardware
Lines of text with boxes and confidence scoresPP-OCRv6PaddleOCRCPU is fine; tiny/small tiers for edge devices
Markdown/JSON with layout, tables, formulas, reading orderPP-StructureV3PPStructureV3CPU works; GPU recommended for volume
Highest document-parsing accuracy from a vision-language modelPaddleOCR-VLPaddleOCRVLNVIDIA GPU or a VLM inference server
Many pages per second on your own GPU fleetHPD-Parsingsee sectionGPU
OCR inside a web page, no serverPaddleOCR.jsJavaScriptBrowser (WebAssembly / WebGPU)
Independent site. paddleocr.dev is not run by Baidu or the PaddleOCR maintainers. For authoritative references use the GitHub repository and the official documentation. Last reviewed: October 2026 against PaddleOCR 3.7.0. See our editorial policy.

Installation

PaddleOCR needs an inference engine (PaddlePaddle) plus the paddleocr package. Install the engine first, then PaddleOCR. Use a virtual environment.

Requirements

  • Python 3.9–3.13 in practice. The paddleocr package declares >=3.8, but PaddlePaddle 3.x wheels target 3.9–3.13, and document parsing needs 3.9+.
  • OS: Linux, Windows or macOS (Apple Silicon runs on CPU).
  • NVIDIA GPU (optional): a driver that supports the CUDA build you install (CUDA 12.6 below; a CUDA 11.8 build is also published).

CPU

Terminal
python -m pip install paddlepaddle==3.2.1 -i https://www.paddlepaddle.org.cn/packages/stable/cpu/
python -m pip install "paddleocr[all]"

NVIDIA GPU (CUDA 12.6)

Terminal
python -m pip install paddlepaddle-gpu==3.2.1 -i https://www.paddlepaddle.org.cn/packages/stable/cu126/
python -m pip install "paddleocr[all]"

Do not run pip install paddlepaddle-gpu from PyPI. The newest GPU build on PyPI is 2.6.2, which PaddleOCR 3.x does not support. Always use the -i index above. Pick the matching CUDA index (for example cu118) from the official PaddlePaddle install selector.

Extras

InstallGives you
paddleocrBasic text recognition (the PaddleOCR class)
"paddleocr[doc-parser]"Document parsing: PP-StructureV3, PaddleOCR-VL
"paddleocr[ie]"Information extraction (PP-ChatOCRv4, PP-DocTranslation)
"paddleocr[trans]"Document translation
"paddleocr[all]"All of the above

Verify

verify.py
import paddle
paddle.utils.run_check()

from paddleocr import PaddleOCR
print("PaddleOCR import OK")

The first real run downloads model weights (from Hugging Face by default), so it needs network access once. To use pre-downloaded models, pass text_detection_model_dir and text_recognition_model_dir.

Quick start: first OCR in five lines

PaddleOCR 3.x returns result objects. Call predict() and read fields such as rec_texts, rec_scores and rec_boxes.

first_ocr.py
from paddleocr import PaddleOCR

ocr = PaddleOCR(lang="en")            # default model for "en" is PP-OCRv6 (medium)
result = ocr.predict("invoice.jpg")  # a path, URL, numpy array or PDF

for res in result:
    for text, score, box in zip(res["rec_texts"], res["rec_scores"], res["rec_boxes"]):
        if score >= 0.8:
            print(f"{score:.2f}  {box.tolist()}  {text}")

    res.save_to_img("output")        # annotated image
    res.save_to_json("output")       # structured result

Command line

Terminal
paddleocr ocr -i invoice.jpg --lang en --save_path ./output

Result fields

FieldMeaning
rec_textsRecognized text, one string per detected line
rec_scoresConfidence per line, 0.0–1.0
rec_boxesAxis-aligned box per line: [x1, y1, x2, y2]
rec_polys / dt_polysFour-point polygons (follow rotated or skewed text)
doc_preprocessor_resOrientation / unwarping info when those modules are on

Want to try options visually? Use the code generator on the homepage, which outputs a runnable snippet and CLI command for your setup.

Migrating from PaddleOCR 2.x

PaddleOCR 3.x is not backward compatible. Most old tutorials (and old AI-generated answers) still show the 2.x API. These are the changes that break code:

2.x3.x
PaddleOCR(use_gpu=True)PaddleOCR(device="gpu") (or "gpu:0"). use_gpu now raises ValueError: Unknown argument: use_gpu.
ocr.ocr(img, cls=True)ocr.predict(img). Orientation handling is configured when you create the object.
use_angle_cls=Trueuse_textline_orientation=True
show_log=...Removed; control logging with the standard logging module.
det_db_thresh, det_db_box_thresh, det_db_unclip_ratiotext_det_thresh, text_det_box_thresh, text_det_unclip_ratio (old names are deprecated and cannot be mixed with the new ones)
rec_batch_numtext_recognition_batch_size
PPStructurePPStructureV3
Nested lists: [[box, (text, score)], ...]Result objects with print(), save_to_json(), save_to_img(), and dict-style fields
migrate.py
# 2.x
# ocr = PaddleOCR(use_angle_cls=True, lang="en", use_gpu=True)
# result = ocr.ocr("img.jpg", cls=True)

# 3.x
from paddleocr import PaddleOCR
ocr = PaddleOCR(lang="en", device="gpu", use_textline_orientation=True)
result = ocr.predict("img.jpg")
for res in result:
    print(res["rec_texts"])

PP-OCRv6: text detection and recognition

PP-OCRv6 shipped with PaddleOCR 3.7.0 (June 11, 2026) and is the default model for the PaddleOCR class. Figures below are Baidu's own reporting; we have not independently benchmarked them.

TierParametersModel names (examples)Use for
Tiny1.5MPP-OCRv6_tiny_det, PP-OCRv6_tiny_recEdge devices, browsers, very low latency
Small7.7MPP-OCRv6_small_det, PP-OCRv6_small_recMobile and CPU services
Medium34.5MPP-OCRv6_medium (default for lang="en")Best accuracy on server hardware
  • Languages: one recognition model covers 50 languages: Chinese, English, Japanese and 46 Latin-script languages. Other scripts (Korean, Arabic, Russian, Thai, Greek and more) use PP-OCRv5 multilingual models; lang="korean" loads korean_PP-OCRv5_mobile_rec.
  • Reported gains: the medium tier improves detection by 4.6% and recognition by 5.1% over PP-OCRv5_server; Baidu reports a 5.2× end-to-end CPU speedup with OpenVINO (6.1× on Apple M4 for tiny).

Choose a tier

tiers.py
from paddleocr import PaddleOCR

# Default (medium)
ocr = PaddleOCR(lang="en")

# Small / tiny: pass both model names
ocr_small = PaddleOCR(
    text_detection_model_name="PP-OCRv6_small_det",
    text_recognition_model_name="PP-OCRv6_small_rec",
)

# Stay on the previous generation
ocr_v5 = PaddleOCR(lang="en", ocr_version="PP-OCRv5")

PP-OCRv5 vs PP-OCRv6

ocr_version accepts "PP-OCRv6", "PP-OCRv5", "PP-OCRv4" and "PP-OCRv3", but not every language exists in every version. If a lang is missing for the version you request, choose another version or pass explicit model names. Pin ocr_version if you need reproducible output across upgrades.

Main parameters

langstre.g. "en"
Recognition language. See language codes.
ocr_versionstrPP-OCRv6
Model generation: PP-OCRv6 / v5 / v4 / v3.
devicestrauto
"cpu", "gpu", "gpu:0", "npu:0", "xpu:0", "mlu:0".
use_doc_orientation_classifyboolTrue
Fix whole-page rotation (0/90/180/270°). Turn off for clean, upright inputs to save time.
use_doc_unwarpingboolTrue
Flatten curved or photographed pages. Turn off for scans and screenshots.
use_textline_orientationboolTrue
Correct upside-down individual lines.
text_det_threshfloat0.3
Pixel threshold on the detection probability map. Lower finds more faint text, with more noise.
text_det_box_threshfloat0.6
Average score a region needs to be kept as a text box.
text_det_unclip_ratiofloat2.0
How much detected regions are expanded. Larger values give looser boxes.
text_rec_score_threshfloat0.0
Drop recognized lines below this confidence.
return_word_boxboolFalse
Also return word-level boxes.
text_recognition_batch_sizeint1
Lines recognized per batch. Raise on GPU.

Defaults are from the official OCR pipeline reference; check the pipeline page for your installed version because defaults and tier names evolve.

PP-StructureV3: documents to Markdown and JSON

PP-StructureV3 combines layout detection, OCR, table recognition, formula recognition, seal recognition and reading-order recovery. It is the right choice when you want a PDF or page image turned into Markdown or JSON rather than a flat list of text lines. It runs on CPU, but is much faster on GPU.

structure.py
from paddleocr import PPStructureV3

pipeline = PPStructureV3(lang="en")   # add device="gpu" if available
output = pipeline.predict("report.pdf")

for res in output:
    res.print()
    res.save_to_json(save_path="output")
    res.save_to_markdown(save_path="output")
Terminal
paddleocr pp_structurev3 -i report.pdf --device cpu --save_path ./output

Install the extra first: python -m pip install "paddleocr[doc-parser]". Useful switches on the constructor and the CLI: use_doc_orientation_classify, use_doc_unwarping, use_textline_orientation, and per-module toggles for tables, formulas, seals and charts. Disable what you do not need for speed.

Practical tips

  • Render PDFs at around 150–200 DPI if you rasterize them yourself; very high DPI slows everything without improving accuracy much.
  • Multi-page PDFs return one result per page. Concatenate the Markdown yourself or use the pipeline's page-merging helpers if your version provides them.
  • Always spot-check tables. Merged cells and borderless tables are where every table-recognition model makes mistakes.

PaddleOCR-VL: vision-language document parsing

PaddleOCR-VL is a compact vision-language model for document parsing (text, tables, formulas, charts) with multilingual support. PaddleOCR-VL-1.6 arrived in PaddleOCR 3.6.0 (May 28, 2026) and is reported by Baidu at 96.33% on OmniDocBench v1.6 (self-reported). It is the most accurate option here but needs a capable GPU or a dedicated inference server; CPU works but the official docs do not recommend it for production.

Terminal
python -m pip install paddlepaddle-gpu==3.2.1 -i https://www.paddlepaddle.org.cn/packages/stable/cu126/
python -m pip install -U "paddleocr[doc-parser]"
vl.py
from paddleocr import PaddleOCRVL

pipeline = PaddleOCRVL()                     # or PaddleOCRVL(device="cpu") for a slow trial run
output = pipeline.predict("page.png")

for res in output:
    res.print()
    res.save_to_json(save_path="output")
    res.save_to_markdown(save_path="output")
Terminal
paddleocr doc_parser -i page.png --save_path ./output

Multi-page documents

vl_pages.py
from paddleocr import PaddleOCRVL

pipeline = PaddleOCRVL()
pages = list(pipeline.predict("contract.pdf"))
merged = pipeline.restructure_pages(pages, merge_tables=True, relevel_titles=True, concatenate_pages=True)

for res in merged:
    res.save_to_markdown(save_path="output")

Inference engines

PaddleOCRVL(engine="transformers") runs the model through Hugging Face Transformers instead of the Paddle engine. For throughput, the docs describe running the VLM behind a dedicated inference server (such as vLLM or SGLang) and pointing PaddleOCR-VL at it via vl_rec_backend; follow the official PaddleOCR-VL page for the exact settings of your version.

HPD-Parsing: high-throughput parsing

HPD-Parsing was announced by the PaddleOCR team on July 22, 2026 as a high-throughput document-parsing model aimed at large batch workloads on GPUs. It is newer and less documented than the other pipelines, so we deliberately do not repeat throughput numbers here. Read the release notes and the official docs for model download, supported hardware and benchmark methodology before planning capacity around it, and benchmark on your own documents.

Performance tuning

Measure first. These are the levers that usually matter, roughly in order of payoff:

  1. Turn off modules you do not need. For clean scans: use_doc_orientation_classify=False, use_doc_unwarping=False, use_textline_orientation=False.
  2. Pick a smaller tier (small or tiny) when accuracy on your documents is already sufficient.
  3. Reuse the object. Create PaddleOCR(...) once; model loading dominates a single call.
  4. Raise batch sizes on GPU (text_recognition_batch_size).
  5. Resize big inputs. Lower text_det_limit_side_len or downscale huge photos before OCR.
  6. CPU: keep enable_mkldnn on and tune cpu_threads; consider the OpenVINO engine on Intel CPUs.
  7. High-performance inference: enable_hpi=True picks an optimized backend automatically. It currently supports Python 3.8–3.12 on Linux x86-64 and needs extra plugins; see the official guide.
tuned.py
from paddleocr import PaddleOCR

ocr = PaddleOCR(
    lang="en",
    device="gpu",
    use_doc_orientation_classify=False,
    use_doc_unwarping=False,
    use_textline_orientation=False,
    text_recognition_batch_size=16,
)

GPU and other accelerators

Set device: "gpu"/"gpu:0" for NVIDIA, and "npu:0", "xpu:0", "mlu:0" and others on supported Chinese accelerators (these need the matching PaddlePaddle build). On macOS use CPU. If the GPU is not used, paddle.device.get_device() should print gpu:0; if it prints cpu you installed the CPU wheel.

Batch processing

batch.py
from pathlib import Path
from paddleocr import PaddleOCR

ocr = PaddleOCR(lang="en", use_doc_orientation_classify=False, use_doc_unwarping=False)
files = sorted(str(p) for p in Path("scans").glob("*.jpg"))

# predict() accepts a list and returns one result per input
for res in ocr.predict(files):
    name = Path(res["input_path"]).stem
    res.save_to_json(f"output/{name}")

Custom models

Use your own trained or exported models by directory: PaddleOCR(text_detection_model_dir="./my_det", text_recognition_model_dir="./my_rec"), optionally with text_detection_model_name / text_recognition_model_name. Training and fine-tuning are covered in the official docs; for most printed text, tuning thresholds and preprocessing is a cheaper first step than training.

RAG and LLM pipelines

For retrieval-augmented generation, parse documents to Markdown, split by headings, and embed the chunks. PP-StructureV3 and PaddleOCR-VL already emit heading-aware Markdown, which makes chunking far cleaner than splitting raw OCR lines.

rag_chunks.py
from pathlib import Path
from paddleocr import PPStructureV3

pipeline = PPStructureV3(lang="en")
md_parts = []
for res in pipeline.predict("handbook.pdf"):
    res.save_to_markdown(save_path="md")

text = "\n\n".join(p.read_text(encoding="utf-8") for p in sorted(Path("md").glob("*.md")))

# split on level-2 headings; replace with your splitter of choice
chunks = [c.strip() for c in text.split("\n## ") if c.strip()]
print(len(chunks), "chunks")
  • Keep page numbers and source file in chunk metadata so answers can cite.
  • Store the OCR confidence for low-quality scans and flag low-confidence chunks.
  • Never assume extracted numbers are correct; for invoices and finance, validate (totals, dates, checksums).

Dify, RAGFlow and other platforms

Most no-code platforms call OCR over HTTP. Run PaddleOCR as a service (see Docker and the serving API below) and call it from the platform's HTTP/tool node, or use the platform's own PaddleOCR connector if it ships one. Check the platform's current docs, because connector names and options change often.

Serving over HTTP

Terminal
paddlex --install serving
paddlex --serve --pipeline OCR          # listens on port 8080 by default
client.py
import base64, requests

with open("demo.jpg", "rb") as f:
    payload = {"file": base64.b64encode(f.read()).decode("ascii"), "fileType": 1}  # 1 = image, 0 = PDF

r = requests.post("http://localhost:8080/ocr", json=payload, timeout=120)
r.raise_for_status()
for res in r.json()["result"]["ocrResults"]:
    print(res["prunedResult"])

Details, authentication and scaling options are in the official serving guide. Do not expose this port to the internet without your own authentication layer.

MCP server for AI agents

The official paddleocr-mcp package (0.8.5 at the time of writing, Python 3.10+) exposes OCR, PP-StructureV3 or PaddleOCR-VL as a Model Context Protocol tool, so a host such as Claude Desktop can read images and PDFs.

Terminal
python -m pip install "paddleocr-mcp[local-cpu]"      # local CPU inference
# or: python -m pip install paddleocr-mcp               # use a hosted / self-hosted backend only

Choose the model with --model (or PADDLEOCR_MCP_MODEL): PP-OCRv6 (default), PP-OCRv5, PP-OCRv5-latin, PP-StructureV3, PaddleOCR-VL, PaddleOCR-VL-1.5, PaddleOCR-VL-1.6. Choose where inference runs with --ppocr_source: local (default), aistudio, qianfan, or self_hosted. Use --http for Streamable HTTP instead of stdio (binds 127.0.0.1:8000 by default).

claude_desktop_config.json
{
  "mcpServers": {
    "paddleocr": {
      "command": "paddleocr_mcp",
      "args": ["--model", "PP-OCRv6", "--ppocr_source", "local"]
    }
  }
}
Privacy: with local, files stay on your machine. With aistudio or qianfan, your documents are uploaded to those services. Pick deliberately.

JavaScript and browser OCR

@paddleocr/paddleocr-js (0.4.2 at the time of writing, Apache-2.0) runs PaddleOCR models in the browser using ONNX Runtime Web and OpenCV.js. Images never leave the user's device. It is a young package (version 0.x), so pin the version and expect API changes.

Terminal
npm install @paddleocr/paddleocr-js
ocr.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);   // predict() returns an array, one entry per image
console.log(result.items);

With ocrVersion: "PP-OCRv6" the SDK uses the PP-OCRv6 small pair; for tiny, pass textDetectionModelName: "PP-OCRv6_tiny_det" and textRecognitionModelName: "PP-OCRv6_tiny_rec". Self-hosting model archives and WASM files is supported; see the package README. Model download size and first-load time matter on mobile networks, so show a loading state.

Docker

A minimal CPU container. This is an example recipe, not an official image; test it on your own base image and hardware.

Dockerfile
FROM python:3.12-slim

# OpenCV runtime libraries (needed if you see "libGL.so.1" or "libgthread" errors)
RUN apt-get update && apt-get install -y --no-install-recommends libgl1 libglib2.0-0 \
    && rm -rf /var/lib/apt/lists/*

RUN python -m pip install --no-cache-dir paddlepaddle==3.2.1 -i https://www.paddlepaddle.org.cn/packages/stable/cpu/ \
    && python -m pip install --no-cache-dir "paddleocr[all]"

WORKDIR /app
COPY app.py .
CMD ["python", "app.py"]
  • Cache models. Mount a volume for ~/.paddlex (where models are cached) so containers do not re-download weights on every start.
  • GPU: use a CUDA base image, install the paddlepaddle-gpu wheel from the CUDA index, and run with --gpus all (needs the NVIDIA Container Toolkit on the host).
  • Air-gapped: pre-download models and pass the *_model_dir arguments.

Python API reference

ClassImportUse
PaddleOCRfrom paddleocr import PaddleOCRText detection + recognition
PPStructureV3from paddleocr import PPStructureV3Layout, tables, formulas to Markdown/JSON
PaddleOCRVLfrom paddleocr import PaddleOCRVLVision-language document parsing
PPChatOCRv4Docfrom paddleocr import PPChatOCRv4DocKey information extraction with an LLM (needs paddleocr[ie])

Methods on every pipeline

predict(input, **kwargs)generator/list
Run inference. input may be a path, URL, numpy array, directory or a list of those; PDFs are supported. Call-time keyword arguments override constructor defaults for that call.
predict_iter(input, **kwargs)generator
Lazy variant for large inputs.

Result object

res["rec_texts"] …dict-like
Fields are read like a dict (see result fields).
res.print()method
Pretty-print the result.
res.save_to_json(path)method
Write structured JSON.
res.save_to_img(path)method
Write the annotated image (OCR pipeline).
res.save_to_markdown(path)method
Write Markdown (document pipelines).

The authoritative parameter lists live in the official pipeline pages for OCR, PP-StructureV3 and PaddleOCR-VL.

Command-line reference

CommandPurpose
paddleocr ocr -i IMGText OCR
paddleocr pp_structurev3 -i FILEDocument to Markdown/JSON
paddleocr doc_parser -i FILEPaddleOCR-VL document parsing
Terminal
paddleocr ocr -i ./scan.png --lang en --device gpu:0 --save_path ./output
paddleocr ocr -i ./scan.png --ocr_version PP-OCRv5
paddleocr ocr -i ./scan.png --use_doc_orientation_classify False --use_doc_unwarping False --use_textline_orientation False
paddleocr pp_structurev3 -i report.pdf --device cpu --save_path ./output
paddleocr doc_parser -i page.png --save_path ./output

Flags mirror the Python constructor arguments: -i/--input, --lang, --ocr_version, --device, --save_path, and the --use_* toggles. Run paddleocr ocr --help for the list your version supports. The old 2.x flags --image_dir, --use_gpu and --use_angle_cls no longer work.

Language codes

Pass a code through lang. Common values:

CodeLanguageModel family
enEnglishPP-OCRv6 (50-language model)
chChinese (Simplified) + EnglishPP-OCRv6
chinese_chtChinese (Traditional)PP-OCRv5
japanJapanesePP-OCRv6
koreanKoreanPP-OCRv5 (korean_PP-OCRv5_mobile_rec)
latin, fr, de, es, it, pt …Latin-script languagesPP-OCRv6 / PP-OCRv5 latin
cyrillic, ruRussian and CyrillicPP-OCRv5
arabic, th, el, devanagari, ta, te …Other scriptsPP-OCRv5

The full, version-specific mapping is the table in the appendix of the official OCR pipeline page. Treat it as the source of truth, since language coverage changes between releases.

Troubleshooting

ValueError: Unknown argument: use_gpu

You are using a 2.x tutorial with 3.x. Use PaddleOCR(device="gpu"). See migration.

pip cannot find a matching paddlepaddle-gpu

PyPI only has an old 2.6.2 GPU build. Install from the PaddlePaddle index with -i https://www.paddlepaddle.org.cn/packages/stable/cu126/ (or the CUDA version you need).

It runs on CPU even though I have a GPU

You probably installed the CPU wheel, or pass device="cpu". Check python -c "import paddle; print(paddle.device.get_device())" and nvidia-smi.

Very slow first run

Models are being downloaded and initialized. Later runs reuse the cache. Reuse a single PaddleOCR object in services.

Empty or garbled results

  • Wrong lang for the script: Korean, Arabic and Russian are not in the 50-language PP-OCRv6 model.
  • Tiny text: upscale the image or raise text_det_limit_side_len.
  • Faint text: lower text_det_thresh and text_det_box_thresh slightly.
  • Photographed pages: enable use_doc_unwarping; scans and screenshots: disable it.

ImportError: libGL.so.1 (Linux / Docker)

Install the OpenCV runtime libraries: apt-get install -y libgl1 libglib2.0-0.

Out of GPU memory

Lower batch sizes, process one page at a time, use a smaller tier, or run PaddleOCR-VL behind a dedicated inference server.

Still stuck? Search the official issue tracker and include your PaddleOCR and PaddlePaddle versions.

Release history

Dates are PyPI upload dates for the paddleocr package. Full notes are on the GitHub releases page.

VersionDateNotable
3.7.0June 11, 2026PP-OCRv6 (tiny / small / medium) becomes the default OCR model
3.6.0May 28, 2026PaddleOCR-VL-1.6
3.5.0April 21, 2026Earlier 3.x feature release
3.4.1April 14, 2026Patch release
3.4.0January 29, 2026Earlier 3.x feature release
3.3.3January 20, 2026Patch release

HPD-Parsing was announced on July 22, 2026 (a model announcement, not a PyPI release).