PaddleOCR Implementation
This guide shows how to build and deploy an OCR API using FastAPI and PaddleOCR. The final system lets a user upload an image, sends it to a Python API, runs PaddleOCR, and returns extracted text through a secure HTTPS endpoint.
Final Architectureβ
AI document intelligence workflow from upload through OCR, extraction, validation, review, and final output.
User
|
v
Next.js frontend
|
v
FastAPI backend on VPS
|
v
PaddleOCR engine
|
v
Text result
The production flow is:
https://api.yoursite.com/ocr
|
v
Nginx reverse proxy
|
v
FastAPI running on 127.0.0.1:8000
|
v
PaddleOCR
What You Needβ
- A Python backend project.
- A VPS running Ubuntu 22.04 or newer.
- A domain from Namecheap, GoDaddy, or another registrar.
- SSH access to the VPS.
- Basic GitHub repository access.
Use at least 2 GB RAM for a small PaddleOCR server. For high-volume OCR or large PDFs, use a larger VPS or a GPU-backed worker.
Build The Backendβ
Create the project:
mkdir ocr-project
cd ocr-project
mkdir backend
cd backend
Create and activate a virtual environment:
python3 -m venv venv
source venv/bin/activate
Install the backend packages:
pip install fastapi uvicorn paddleocr paddlepaddle python-multipart
Create main.py:
from fastapi import FastAPI, UploadFile, File
from paddleocr import PaddleOCR
import os
import shutil
import uuid
app = FastAPI()
ocr = PaddleOCR(use_angle_cls=True, lang="en")
@app.get("/health")
def health():
return {"ok": True}
@app.post("/ocr")
async def run_ocr(file: UploadFile = File(...)):
os.makedirs("uploads", exist_ok=True)
temp_file = f"uploads/{uuid.uuid4()}.jpg"
with open(temp_file, "wb") as buffer:
shutil.copyfileobj(file.file, buffer)
result = ocr.ocr(temp_file)
text = ""
for page in result:
for line in page:
text += line[1][0] + "\n"
os.remove(temp_file)
return {"text": text}
Run locally:
uvicorn main:app --reload
Open:
http://127.0.0.1:8000/health
http://127.0.0.1:8000/docs
Use /docs to upload an image and test /ocr.
Run An Existing Projectβ
If the project already exists and has an app/ folder, run it from the project root, not from inside app.
cd path/to/idsp-py
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
Then try the most common FastAPI import path:
uvicorn app.main:app --reload
If that fails, inspect the app folder:
ls app
Other common run commands are:
uvicorn app.api:app --reload
uvicorn app.server:app --reload
Open the API docs:
http://127.0.0.1:8000/docs
For a live VPS server, run:
uvicorn app.main:app --host 0.0.0.0 --port 8000
Fix PaddlePaddle Install Errorsβ
If installation fails with:
ERROR: No matching distribution found for paddlepaddle==3.2.0
the pinned version in requirements.txt is not available for your Python and operating system combination.
Change:
paddlepaddle==3.2.0
to:
paddlepaddle
or use a newer supported version:
paddlepaddle==3.3.1
Then reinstall:
pip install --upgrade pip setuptools wheel
pip install -r requirements.txt
If it still fails, install PaddlePaddle and PaddleOCR manually first:
pip install paddlepaddle
pip install paddleocr
pip install -r requirements.txt
Check your Python version:
python3 --version
Use Python 3.10 or 3.11 when possible. PaddlePaddle wheels depend on Python version, CPU architecture, and operating system.
Buy And Prepare A VPSβ
Create a VPS from a provider such as DigitalOcean or Hetzner.
Recommended starting setup:
- Ubuntu 22.04.
- 2 GB RAM minimum.
- SSH access enabled.
Connect to the server:
ssh root@YOUR_SERVER_IP
Install server packages:
apt update
apt install python3 python3-pip python3-venv nginx git -y
Upload Code To VPSβ
Push the backend to GitHub from your computer:
git init
git add .
git commit -m "first commit"
git remote add origin https://github.com/yourname/ocr-project.git
git push -u origin main
Clone it on the VPS:
git clone https://github.com/yourname/ocr-project.git
cd ocr-project/backend
Install the backend:
python3 -m venv venv
source venv/bin/activate
pip install fastapi uvicorn paddleocr paddlepaddle python-multipart
Run it:
uvicorn main:app --host 0.0.0.0 --port 8000
Test:
http://YOUR_SERVER_IP:8000/health
Keep The App Running With Supervisorβ
Do not rely on a terminal session to keep the API alive. Use Supervisor.
Install Supervisor:
apt install supervisor -y
Create the config:
nano /etc/supervisor/conf.d/ocr.conf
Paste:
[program:ocr]
directory=/root/ocr-project/backend
command=/root/ocr-project/backend/venv/bin/uvicorn main:app --host 127.0.0.1 --port 8000
autostart=true
autorestart=true
Start the program:
supervisorctl reread
supervisorctl update
supervisorctl start ocr
The API now runs locally on the VPS at:
http://127.0.0.1:8000
Nginx will expose it publicly.
Connect A Domainβ
In your domain provider, open DNS or Advanced DNS settings.
Add an A record:
Type: A Record
Host: api
Value: YOUR_SERVER_IP
TTL: Automatic
This maps:
api.yoursite.com -> YOUR_SERVER_IP
DNS propagation usually takes 5 to 30 minutes, but it can take longer.
Test:
ping api.yoursite.com
Configure Nginxβ
Create a site config:
nano /etc/nginx/sites-available/ocr
Paste:
server {
listen 80;
server_name api.yoursite.com;
location / {
proxy_pass http://127.0.0.1:8000;
}
}
Enable it:
ln -s /etc/nginx/sites-available/ocr /etc/nginx/sites-enabled/
nginx -t
systemctl restart nginx
Test:
http://api.yoursite.com/health
Add HTTPS With Certbotβ
Install Certbot:
apt install certbot python3-certbot-nginx -y
Generate SSL:
certbot --nginx -d api.yoursite.com
Follow the prompts:
- Enter your email.
- Agree to the terms.
- Choose HTTP to HTTPS redirect.
Test:
https://api.yoursite.com/health
Certbot automatically renews Let's Encrypt certificates before they expire.
Update The Appβ
On your computer:
git add .
git commit -m "update"
git push
On the VPS:
cd /root/ocr-project/backend
git pull
source venv/bin/activate
supervisorctl restart ocr
Optional Docker Deploymentβ
Docker keeps deployment consistent across machines and avoids many dependency issues.
Install Docker:
apt update
apt install docker.io -y
systemctl start docker
systemctl enable docker
Create Dockerfile inside the backend folder:
FROM python:3.10
WORKDIR /app
COPY . .
RUN pip install --no-cache-dir fastapi uvicorn paddleocr paddlepaddle python-multipart
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Build the image:
docker build -t ocr-api .
Run the container:
docker run -d -p 8000:8000 ocr-api
Test:
http://YOUR_SERVER_IP:8000/health
With Docker, the production path is:
Domain -> Nginx -> Docker container -> FastAPI -> PaddleOCR
To update:
git pull
docker build -t ocr-api .
docker stop $(docker ps -q)
docker run -d -p 8000:8000 ocr-api
For multiple containers, use Docker Compose instead of stopping every running container.
Production Checklistβ
- Use
/healthfor uptime checks. - Keep uploaded files in a temporary folder and delete them after OCR.
- Store original documents only when the product requires it.
- Put FastAPI behind Nginx instead of exposing Uvicorn directly.
- Use HTTPS for all public endpoints.
- Use Supervisor, systemd, or Docker to keep the process running.
- Log OCR failures and slow requests.
- Add file size limits before accepting uploads.
- Validate extracted text before using it for business decisions.
Final Understandingβ
- VPS is your online server.
- GitHub stores and transfers your code.
- FastAPI exposes the OCR API.
- PaddleOCR reads text from images and documents.
- Supervisor keeps the Python API running.
- Nginx routes public traffic to the local API.
- SSL makes the API secure with HTTPS.
- Docker makes deployment easier and repeatable.
Frontend platforms like Vercel auto-deploy from GitHub, but backend APIs on a VPS require manual setup. You connect through SSH, pull the code, run the app, route traffic with Nginx, secure it with SSL, and optionally use Docker for simplified deployment.