BentoPDF uses three AGPL-licensed WASM libraries to power advanced PDF features. By default, these libraries are loaded at runtime from jsDelivr CDN — no configuration needed.
For custom deployments (air-gapped networks, self-hosted infrastructure, or CDN restrictions), you can override the URLs at build time.
AGPL components
| Component | License | Features |
|---|
| PyMuPDF | AGPL-3.0 | PDF to Text/Markdown/SVG/DOCX, extract images/tables, EPUB/MOBI/XPS conversion, compression, deskew |
| Ghostscript | AGPL-3.0 | PDF/A conversion, font to outline |
| CoherentPDF | AGPL-3.0 | Merge (preserve bookmarks), split by bookmarks, table of contents, PDF to/from JSON, attachments |
BentoPDF does not bundle these libraries in its source code. It pre-configures CDN URLs so that the user’s browser downloads them at runtime. The URLs themselves are baked into the JavaScript bundle at build time — changing them after the image is built has no effect.
Default configuration
The following defaults are set in .env.production and work out of the box:
# WASM module URLs
VITE_WASM_PYMUPDF_URL=https://cdn.jsdelivr.net/npm/@bentopdf/[email protected]/
VITE_WASM_GS_URL=https://cdn.jsdelivr.net/npm/@bentopdf/gs-wasm/assets/
VITE_WASM_CPDF_URL=https://cdn.jsdelivr.net/npm/coherentpdf/dist/
# OCR assets (Tesseract.js) — leave empty to use Tesseract.js runtime defaults
VITE_TESSERACT_WORKER_URL=
VITE_TESSERACT_CORE_URL=
VITE_TESSERACT_LANG_URL=
VITE_TESSERACT_AVAILABLE_LANGUAGES=
VITE_OCR_FONT_BASE_URL=
Overriding WASM URLs
You can override any WASM URL at build time to point to your own server or internal mirror.
Docker build args
.env.production
Pass the URLs as Docker build arguments:docker build \
--build-arg VITE_WASM_PYMUPDF_URL=https://your-server.com/pymupdf/ \
--build-arg VITE_WASM_GS_URL=https://your-server.com/gs/ \
--build-arg VITE_WASM_CPDF_URL=https://your-server.com/cpdf/ \
--build-arg VITE_TESSERACT_WORKER_URL=https://your-server.com/ocr/worker.min.js \
--build-arg VITE_TESSERACT_CORE_URL=https://your-server.com/ocr/core \
--build-arg VITE_TESSERACT_LANG_URL=https://your-server.com/ocr/lang-data \
--build-arg VITE_TESSERACT_AVAILABLE_LANGUAGES=eng,deu \
--build-arg VITE_OCR_FONT_BASE_URL=https://your-server.com/ocr/fonts \
-t bentopdf .
Edit .env.production in the project root before running npm run build:VITE_WASM_PYMUPDF_URL=https://your-server.com/pymupdf/
VITE_WASM_GS_URL=https://your-server.com/gs/
VITE_WASM_CPDF_URL=https://your-server.com/cpdf/
VITE_TESSERACT_WORKER_URL=https://your-server.com/ocr/worker.min.js
VITE_TESSERACT_CORE_URL=https://your-server.com/ocr/core
VITE_TESSERACT_LANG_URL=https://your-server.com/ocr/lang-data
VITE_TESSERACT_AVAILABLE_LANGUAGES=eng,deu
VITE_OCR_FONT_BASE_URL=https://your-server.com/ocr/fonts
Then build:
CDN optimization
When building from source, you can enable CDN optimization so the browser loads large WASM files from jsDelivr, with local files as an automatic fallback:
VITE_USE_CDN=true npm run build
When VITE_USE_CDN=true is set, jsDelivr is the primary source and local WASM files serve as fallback if the CDN is unreachable.
OCR configuration
OCR is powered by Tesseract.js. By default, Tesseract.js uses its own runtime defaults for worker and core URLs.
For self-hosted or air-gapped deployments, set all three Tesseract variables together:
VITE_TESSERACT_WORKER_URL=https://your-server.com/ocr/worker.min.js
VITE_TESSERACT_CORE_URL=https://your-server.com/ocr/core
VITE_TESSERACT_LANG_URL=https://your-server.com/ocr/lang-data
If you only bundle a subset of OCR languages, also set VITE_TESSERACT_AVAILABLE_LANGUAGES to the same comma-separated list. This limits the UI to only the installed languages and shows a descriptive error for unsupported selections:
VITE_TESSERACT_AVAILABLE_LANGUAGES=eng,deu
For fully offline searchable-PDF output, set VITE_OCR_FONT_BASE_URL to the directory that serves the bundled OCR text-layer fonts:
VITE_OCR_FONT_BASE_URL=https://your-server.com/ocr/fonts
User overrides
Users can override WASM URLs in the app’s Advanced Settings panel in the browser. Browser-side overrides take priority over build-time defaults.
This means you can ship a build with CDN defaults and let individual users point to their own mirrors without requiring a rebuild.
Disabling a module
To disable a WASM module entirely (for example, to prevent PyMuPDF from loading automatically), set its URL variable to an empty string at build time:
docker build --build-arg VITE_WASM_PYMUPDF_URL="" -t bentopdf .
Users who need the disabled module must configure its URL manually via Advanced Settings in the app.
CORS proxy for digital signatures
The Digital Signature tool may need to fetch certificate chain data from external certificate authority servers. Many CA servers do not include CORS headers, and some serve over plain HTTP — both of which browsers block on HTTPS pages. A CORS proxy is required in these cases.
The proxy is only needed when using the Digital Signature tool and only when your certificate requires fetching issuer certificates from external URLs. Self-signed certificates typically do not need it.
Navigate to the Cloudflare directory
Update allowed origins
Open cors-proxy-worker.js and update ALLOWED_ORIGINS to your domain:const ALLOWED_ORIGINS = [
'https://your-domain.com',
'https://www.your-domain.com',
];
Without this step, the proxy will reject all requests from your site with a 403 error. The default value only allows bentopdf.com.
Deploy the worker
npx wrangler login
npx wrangler deploy
Note the worker URL assigned by Cloudflare (e.g., https://bentopdf-cors-proxy.your-subdomain.workers.dev).Set the proxy URL at build time
Pass the worker URL as a Docker build secret:export VITE_CORS_PROXY_URL="https://your-worker-url.workers.dev"
DOCKER_BUILDKIT=1 docker build \
--secret id=VITE_CORS_PROXY_URL,env=VITE_CORS_PROXY_URL \
-t bentopdf .
Or set it in .env.production before building from source:VITE_CORS_PROXY_URL=https://your-worker-url.workers.dev