paperful
Fill the gaps in your Zotero library.
Fetch the PDFs your items are missing. Keep them in a folder tree that mirrors your collections. Attach them back. Work stays on disk. Zotero is a library adapter, not the whole product.
The briefing for missing PDFs
Open access first. Campus EZProxy when you have a subscription. Sci-Hub is opt-in and off by default.
On disk first
Downloads land under out/. Resume lives in
state/. Zotero is read in, then written back —
attach and metadata apply are separate steps.
Routed sources
Each item only hits sources that match its metadata unless you
pass --try-all. A circuit breaker skips blocked
sources for the rest of the run.
Campus when you have it
Log in once with headed Chromium. EZProxy uses your library entitlement. Passwords never live in TOML.
Grey literature
Playbooks rewrite UN, FAO, ISA, and similar landings to PDFs. Optional HTML→PDF covers blogs and news pages.
What can I do with it?
- Fill a collection (or the whole library) with missing PDFs
- Keep a folder tree that matches Zotero collections
- Lint DOIs and propose metadata patches on disk
- Use campus EZProxy without storing your password
- Opt in to Sci-Hub only when you choose to
Walkthrough: commands. Not sure if this is the right tool? comparison · architecture.
On your machine
paperful is a local CLI. Catalogue reads and PDF writes go through
Zotero’s local API. Session cookies stay under
state/sessions/. Sci-Hub stays off until you add it
to sources or pass --scihub.
From a checkout to a filled collection
-
Copy
config.example.toml, setemailandout_dir, then runpaperful doctor. -
List collections with “No PDF” counts:
paperful collections. - Dry-run a collection, then fetch and attach.
- Optionally log in to EZProxy or Scholar before a big run.
Install
Python 3.10+ and uv. Zotero running with the local API enabled.
git clone https://github.com/glen-w/Paperful.git
cd Paperful
uv sync
cp config.example.toml config.toml
uv run paperful doctor
uv run paperful run --collection interesting --dry-run
Details: Documentation · 0.x / 1.0 · README