CLI migration tool to export documents from Paperless-ngx and import them into Papra.
Tip
Try Papra risk-free. This tool copies your documents from Paperless-ngx to Papra without touching your Paperless data. Nothing gets modified, nothing gets deleted — it's read-only on the Paperless side. If you don't like Papra, your Paperless setup is exactly as you left it.
- 📦 Full export — documents, tags, correspondents, and document types from Paperless-ngx
- 🏷️ Metadata preservation — correspondents →
correspondent:tags, document types →type:tags, colors preserved - 📅 Date & ASN encoding — created dates and archive serial numbers embedded in document names
- 🔍 OCR content transfer — full-text search preserved in Papra
- 👀 Dry-run mode — preview what would be migrated without making changes
- 💾 Export-only mode — dump Paperless-ngx data to JSON
- 🔁 Idempotent — safe to re-run, duplicates are skipped via SHA256
Run directly with npx (no install needed):
npx github:b0x42/paperless2papra migrate --helpOr install globally from the latest release:
npm install -g https://github.com/b0x42/paperless2papra/releases/download/v1.0.0/paperless2papra-1.0.0.tgz| Value | Where to get it |
|---|---|
PAPERLESS_URL |
The URL of your Paperless-ngx instance (e.g. http://localhost:8000) |
PAPERLESS_TOKEN |
In Paperless-ngx, go to Settings → API Auth Token |
PAPRA_URL |
The URL of your Papra instance (e.g. http://localhost:1221) |
PAPRA_TOKEN |
In Papra, go to API Keys (/api-keys) and generate a key |
PAPRA_ORG_ID |
In Papra, go to Admin → Organizations (/admin/organizations) |
paperless2papra migrate \
--paperless-url http://localhost:8000 \
--paperless-token YOUR_PAPERLESS_TOKEN \
--papra-url http://localhost:1221 \
--papra-token YOUR_PAPRA_API_KEY \
--papra-org-id YOUR_ORG_IDpaperless2papra dry-run \
--paperless-url http://localhost:8000 \
--paperless-token YOUR_PAPERLESS_TOKENpaperless2papra export-only \
--paperless-url http://localhost:8000 \
--paperless-token YOUR_PAPERLESS_TOKEN \
--output export.jsonAll options can be provided via environment variables instead of flags:
| Flag | Environment Variable |
|---|---|
--paperless-url |
PAPERLESS_URL |
--paperless-token |
PAPERLESS_TOKEN |
--papra-url |
PAPRA_URL |
--papra-token |
PAPRA_TOKEN |
--papra-org-id |
PAPRA_ORG_ID |
See docs/design-decisions.md for full details.
| Paperless-ngx | Papra |
|---|---|
| Document file | Document (uploaded) |
| Document title | Document name (with date/ASN prefix) |
| Tags | Tags (color preserved) |
| Correspondents | Tags with correspondent: prefix |
| Document types | Tags with type: prefix |
| Created date | Encoded in document name: [YYYY-MM-DD] |
| Archive serial number | Encoded in document name: [ASN:n] |
| OCR content | Document content field |
[YYYY-MM-DD] [ASN:n] Original Title.ext
Segments are omitted when not available.
Your Papra API key needs these permissions:
organizations:readdocuments:create,documents:read,documents:updatetags:create,tags:read
# Install dependencies
npm install
# Run from source (no build needed)
npm run dev -- migrate --help
# Build dist/ from src/
npm run build
# Run tests
npm testAfter making changes to src/, run npm run build and commit both src/ and dist/ — the compiled dist/ is committed so the package can be installed directly from GitHub without a build step.