paddleocr-text-recognition

>-

aidenwu0209/paddleocr-skills4.0k installsApache-2.0Synced Aug 31

Works with

Claude CodeCursorCodex CLIGitHub CopilotGemini CLI
---
name: paddleocr-text-recognition
description: >-
license: Apache-2.0
---

# PaddleOCR Text Recognition Skill

## When to Use This Skill

**Trigger keywords (routing)**: Bilingual trigger terms (Chinese and English) are listed in the YAML `description` above—use that field for discovery and routing.

**Use this skill for**:

- Extract text from images (screenshots, photos, scans)
- Extract text from PDFs or document images when the goal is **line/box-level text**, not recovering table grids, formulas, or full reading-order layout
- Extract text from URLs or local files that point to images/PDFs

**Do not use for**:

- Plain text files, code files, or markdown documents that can be read directly as text
- Documents with tables, formulas, charts, or complex layouts — use Document Parsing instead
- Tasks that do not involve image-to-text conversion

## Installation

Scripts declare their dependencies inline ([PEP 723](https://peps.python.org/pep-0723/)). No separate install step is needed — [uv](https://docs.astral.sh/uv/) resolves dependencies automatically:

```bash
uv run scripts/ocr_caller.py --help
```

## How to Use This Skill

> **Working directory**: All `uv run scripts/...` commands below should be run from this skill's root directory (the directory containing this SKILL.md file).

### Basic Workflow

1. **Identify the input source**:
   - User provides URL: Use the `--file-url` parameter
   - User provides local file path: Use the `--file-path` parameter

2. **Execute OCR**:

   ```bash
   uv run scripts/ocr_caller.py --file-url "URL provided by user" --pretty
   ```

   Or for local files:

   ```bash
   uv run scripts/ocr_caller.py --file-path "file path" --pretty
   ```

   > **Performance note**: Parsing time scales with document complexity. Single-page images typically complete in 1-3 seconds; large PDFs (50+ pages) may take several minutes. Allow adequate time before assuming a timeout.

   **Default behavior: save raw JSON to a temp file**:
   - If `--output` is omitted, the script saves automatically under the system temp directory
   - Default path pattern: `<system-temp>/paddleocr/text-recognition/results/result_<timestamp>_<id>.json`
   - If `--output` is provided, it overrides the default temp-file destination
   - If `--stdout` is provided, JSON is printed to stdout and no file is saved
   - In save mode, the script prints the absolute saved path on stderr: `Result saved to: /absolute/path/...`
   - In default/custom save mode, read and parse the saved JSON file before responding
   - Use `--stdout` only when you explicitly want to skip file persistence

3. **Parse JSON response**:
   - In default/custom save mode, load JSON from the saved file path shown by the script
   - Check the `ok` field: `true` means success, `false` means error
   - Extract text: `text` field contains all recognized text
   - If `--stdout` is used, parse the stdout JSON directly
   - Handle errors: If `ok` is false, display `error.message`

4. **Present results to user**:
   - Display extracted text in a readable format
   - If the text is empty, the image may contain no text
   - In save mode, always tell the user the saved file path and that full raw JSON is available there

### What to Do After Extraction

Common next steps once you have the recognized text:

- **Save to file**: Write the `text` field to a `.txt` or `.md` file
- **Search the content**: Search the saved output file for keywords
- **Feed to another pipeline**: The `text` field is clean plain text, ready for downstream processing
- **Poor results**: See "Tips for Better Results" below before retrying

### Complete Output Display

Always display the COMPLETE recognized text to the user. The user typically needs the full content for downstream use — truncation silently loses data they may not notice is missing.

- Display the entire `text` field, no matter how long
- Do not use phrases like "Here's a summary" or "The text begins with..."
- Do not truncate with "..." unless the text truly exceeds reasonable display limits (>10,000 chars)

**Example - Correct**:

```
User: "Extract the text from this image"
Agent: I've extracted the text from the image. Here's the complete content:

[Display the entire text here]
```

**Example - Incorrect**:

```
User: "Extract the text from this image"
Agent: I found some text in the image. Here's a preview:
"The quick brown fox..." (truncated)
```

### Understanding the Output

The script returns a JSON envelope with `ok`, `text`, `result`, and `error` fields. Use `text` for the recognized content; `result` contains the raw API response for debugging.

For the full schema and field-level details, see `references/output_schema.md`.

> Raw result location (default): the temp-file path printed by the script on stderr

### Alternative: paddleocr CLI

This mirror keeps the bundled `scripts/ocr_caller.py` as the default path. The upstream PaddleOCR project (since [PR #18090](https://github.com/PaddlePaddle/PaddleOCR/pull/18090), 2026-06-03) also ships an official CLI that calls the same API directly. If the `paddleocr` package is installed, you can use it as a drop-in alternative — no `uv run` or local scripts required.

**Install** (one-time):

```bash
pip install "paddleocr>=3.7.0"
```

**Environment**: the CLI only needs `PADDLEOCR_ACCESS_TOKEN`. It resolves the API endpoint internally, so `PADDLEOCR_OCR_API_URL` is **not** required when using the CLI (the URL is still required by the script).

**Basic OCR**:

```bash
# From URL
paddleocr api --model_type ocr --file_url "https://example.com/image.png"

# From local file
paddleocr api --model_type ocr --file_path "./document.pdf"
```

**Common options**:

```bash
# Specific model
paddleocr api --model_type ocr --model PP-OCRv5 --file_path "./report.pdf"

# Disable preprocessing (faster, for flat/well-oriented images)
paddleocr api --model_type ocr --file_path "./document.pdf" \
  --use_doc_unwarping False --use_doc_orientation_classify False

# Page ranges
paddleocr api --model_type ocr --file_path "./large.pdf" --page_ranges "1-5,10,15-20"

# Save result to file
paddleocr api --model_type ocr --file_url "https://..." --output result.json
```

**CLI output format** — **different from the script envelope**:

```json
{
  "jobId": "job-xxx",
  "pages": [
    {
      "prunedResult": {
        "rec_texts": ["Line 1", "Line 2"],
        "rec_scores": [0.98, 0.95]
      },
      "ocrImageUrl": "https://..."
    }
  ]
}
```

The CLI prints `{jobId, pages:[...]}` to stdout. It does **not** wrap the response in the script's `{ok, text, result, error}` envelope, does not auto-save to a temp file, and does not concatenate `text` for you. If you switch paths, update your parsing logic accordingly.

**Scripts vs CLI** — at a glance:

| | Scripts (default) | `paddleocr` CLI (alternative) |
| --- | --- | --- |
| Install | `uv` resolves PEP 723 inline deps | `pip install "paddleocr>=3.7.0"` |
| Required env | `PADDLEOCR_OCR_API_URL` + `PADDLEOCR_ACCESS_TOKEN` | `PADDLEOCR_ACCESS_TOKEN` only |
| Entry | `uv run scripts/ocr_caller.py ...` | `paddleocr api --model_type ocr ...` |
| Output | `{ok, text, result, error}` envelope, auto-saved to temp file | `{jobId, pages:[...]}` to stdout |
| Result location | Path printed on stderr (or `--output`/`--stdout`) | stdout (or `--output`) |
| Best for | Skills runtimes, offline-friendly, no extra install | Already have `paddleocr` installed, want the upstream-canonical flow |

Run `paddleocr api --help` for the full option list.

### Usage Examples

**Example 1: URL OCR**

```bash
uv run scripts/ocr_caller.py --file-url "https://example.com/invoice.jpg" --pretty
```

**Example 2: Local File OCR**

```bash
uv run scripts/ocr_caller.py --file-path "./document.pdf" --pretty
```

**Example 3: OCR With Explicit File Type**

```bash
uv run scripts/ocr_caller.py --file-url "https://example.com/input" --file-type 1 --pretty
```

- `--file-type 0`: PDF
- `--file-type 1`: image
- If omitted, the type is auto-detected from the file extension. For local files, a recognized extension (`.pdf`, `.png`, `.jpg`, `.jpeg`, `.bmp`, `.tiff`, `.tif`, `.webp`) is required; otherwise pass `--file-type` explicitly. For URLs with unrecognized extensions, the service attempts inference.

**Example 4: Print JSON Without Saving**

```bash
uv run scripts/ocr_caller.py --file-url "https://example.com/input" --stdout --pretty
```

### First-Time Configuration

**When API is not configured**, the script outputs:

```json
{
  "ok": false,
  "text": "",
  "result": null,
  "error": {
    "code": "CONFIG_ERROR",
    "message": "PADDLEOCR_OCR_API_URL not configured. Get your API at: https://paddleocr.com"
  }
}
```

**Configuration workflow**:

1. **Show the exact error message** to the user.

2. **Guide the user to obtain credentials**: Visit the [PaddleOCR website](https://www.paddleocr.com), click **API**, select the `PP-OCRv5` model, select the language, then copy the `API_URL` and `Token`. They map to these environment variables:
   - `PADDLEOCR_OCR_API_URL` — full endpoint URL ending with `/ocr`
   - `PADDLEOCR_ACCESS_TOKEN` — 40-character alphanumeric string

   Optionally configure `PADDLEOCR_OCR_TIMEOUT` for request timeout. Recommend using the host application's standard configuration method rather than pasting credentials in chat.

3. **Apply credentials** — one of:
   - **User configured via the host UI**: ask the user to confirm, then retry.
   - **User pastes credentials in chat**: warn that they may be stored in conversation history, help the user persist them using the host's standard configuration method, then retry.

### Error Handling

All errors return JSON with `ok: false`. Show the error message and stop — do not fall back to your own vision capabilities. Identify the issue from `error.code` and `error.message`:

**Authentication failed (403)** — `error.message` contains "Authentication failed"

- Token is invalid, reconfigure with correct credentials

**Quota exceeded (429)** — `error.message` contains "API rate limit exceeded"

- Daily API quota exhausted, inform user to wait or upgrade

**Unsupported format** — `error.message` contains "Unsupported file format"

- File format not supported, convert to PDF/PNG/JPG

**No text detected**:

- `text` field is empty
- Image may be blank, corrupted, or contain no text

### Tips for Better Results

If recognition quality is poor:

- **Low resolution**: Provide a higher resolution image (≥300 DPI works well for most printed text)
- **Noisy background**: A cleaner scan or screenshot typically yields better results than a phone photo
- **Check confidence**: The raw JSON (`result.result.ocrResults[n].prunedResult.rec_scores`) shows per-line confidence scores — low values identify uncertain regions worth reviewing

## Reference Documentation

- `references/output_schema.md` — Full output schema, field descriptions, and command examples

> **Note**: Model version, capabilities, and supported file formats are determined by your API endpoint (`PADDLEOCR_OCR_API_URL`) and its official API documentation.

## Testing the Skill

To verify the skill is working properly:

```bash
uv run scripts/smoke_test.py
uv run scripts/smoke_test.py --skip-api-test
uv run scripts/smoke_test.py --test-url "https://..."
```

The first form tests configuration and API connectivity. `--skip-api-test` checks configuration only. `--test-url` overrides the default sample image URL.

More General & Other skills

← All General & Other skills

Check your AI visibility

One URL in, a 0–100 score and the exact fixes out.

RUN THE CHECK

Browse all the tools

15 tools across six categories
13 of them never send your data anywhere

Free · No signup · No trial clock

SEE THE DIRECTORY