Skip to content

Repository files navigation

📝 url2doi

Small CLI, web and REST API for extracting DOI metadata from article URLs.

See it live at 🔗 https://url2doi.onrender.com/.

screenshot

Supported Publishers

Supported and covered by the current test URLs:

  • ✅ Cell Press
  • ✅ Nature
  • ✅ Science / Science Advances / Science Immunology
  • ✅ bioRxiv
  • ✅ AACR

Usage

Create a text file with one URL per line:

https://www.nature.com/articles/d41586-026-02103-5

Run:

uv run url2doi convert urls.txt

Default output is one DOI per line. If a URL cannot be resolved, the command prints a warning with the original URL:

10.1038/d41586-026-02103-5
⚠️ could not retrieve - https://example.com/missing

To export the tab-separated table instead, pass --tsv with an output path:

uv run url2doi convert urls.txt --tsv output/results.tsv

The exported TSV keeps the previous columns:

url	doi	doi_url	status
https://www.nature.com/articles/d41586-026-02103-5	10.1038/d41586-026-02103-5	https://doi.org/10.1038/d41586-026-02103-5	ok

The extractor first checks common publisher meta tags such as citation_doi, dc.identifier, and prism.doi, then falls back to DOI links or DOI-like text in the HTML. For science.org URLs that already embed a DOI under /doi/10.1126/..., and biorxiv.org URLs that embed a DOI under /content/, it extracts that DOI directly without downloading the page. Biorxiv version markers such as v2 are removed from the exported DOI. For Elsevier and Cell URLs that expose a PII in the path, it can also query Crossref and accept the DOI only when Crossref's alternative-id matches that PII.

API

Start the Flask API for local development:

uv run url2doi serve-api

Start it with Gunicorn for production:

uv run url2doi serve-api --production

The production server listens on 0.0.0.0:8000 by default. Pass --host or --port to change the bind address, WEB_CONCURRENCY, WEB_THREADS, or WEB_TIMEOUT to override Gunicorn settings, and --timeout to change the default DOI fetch timeout.

Platforms that expect a WSGI target can also run:

uv run gunicorn url2doi.api.wsgi:app --config gunicorn.conf.py

Extract a DOI from one URL:

curl -X POST http://127.0.0.1:8000/doi \
  -H 'Content-Type: application/json' \
  -d '{"url": "https://www.nature.com/articles/d41586-026-02103-5"}'

The same endpoint also supports GET /doi?url=....

Development

uv sync
uv run python -m unittest discover -s tests

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages