Skip to main content

PyPI - Version PyPI - Types PyPI - Python Version CI docs

pmid-to-citation

Fetch PubMed records from the NCBI Entrez API by PMID and render them as citation/reference text.

Status: pre-1.0. The public API may change between minor releases.

Installation

pip install pmid-to-citation

Quick start

tool and email are required, and deliberately have no defaults: the Entrez usage guidelines require every request to identify its caller, and a library must not answer that on its user's behalf.

import asyncio
from pmid_to_citation import fetch_citation

citation = asyncio.run(fetch_citation(1, tool="my-app", email="me@example.org"))
# 'Makar, A. B., McMartin, K. E., Palese, M. & Tephly, T. R. Formate assay in
#  body fluids: application in methanol poisoning. <i>Biochem Med</i>
#  <b>13</b>, 117–26 (1975).'

The rendered text is an HTML fragment — the Nature style italicises journal names, emboldens volume numbers, and & arrives as &amp;. Treat it as markup, not as plain text.

The three layers

Fetching and formatting are separate, and each layer is usable on its own.

1. Client — talks to Entrez over HTTP, and knows nothing about citations. Reuse one client for several records rather than reconnecting per PMID:

from pmid_to_citation import EntrezClient

async with EntrezClient(tool="my-app", email="me@example.org") as client:
    record = await client.get_record(31341288)
    raw = await client.get_record_text(31341288)  # unparsed MEDLINE text

An NCBI_API_KEY in the environment is picked up automatically; it raises the rate limit from 3 to 10 requests per second.

Many PMIDs at once

EFetch accepts many identifiers per call, so fetching a reference list costs a handful of requests rather than one per PMID:

from pmid_to_citation import fetch_citations

wanted = [1, 31341288, 35642643]
citations = await fetch_citations(wanted, tool="my-app", email="me@example.org")

fetch_records and EntrezClient.get_records do the same for records. All three return a mapping keyed by PMID, and batch requests concurrently at the rate the Entrez guidelines permit.

PMIDs that Entrez does not know are absent from the result rather than raising. Entrez omits them silently, and one retracted or mistyped identifier should not defeat a request for hundreds:

records = await fetch_records(wanted, tool="my-app", email="me@example.org")
missing = [pmid for pmid in wanted if pmid not in records]

Identifiers are split into batches of batch_size (200 by default); raising it switches those requests to POST, as NCBI asks for long lists. Duplicates are requested once.

2. Record models — validated, normalised models of a PubMed record, with no knowledge of HTTP or of output formats. Parse text you obtained anywhere:

from pmid_to_citation import parse_medline, parse_medline_file

record = parse_medline(raw)
record = parse_medline_file("record.txt")
records = parse_medline_records(multi_record_text)  # a multi-PMID response

record.title       # 'Formate assay in body fluids: application in methanol poisoning.'
record.authors[0]  # Author(last_name='Makar', initials='AB', ...)
record.other_fields  # any MEDLINE tag this library does not model, kept verbatim

3. Styles — pure functions from a record to text, with no I/O. Compiling a style is expensive, so reuse a formatter:

from pmid_to_citation import CitationFormatter, CitationStyle

formatter = CitationFormatter(CitationStyle.NATURE)
formatter.format_citation(record)
formatter.format_citations([record, other_record])  # reuses the compiled style

Rendering goes through citeproc-py and a Citation Style Language definition, which is what will make further styles cheap to add. That is an implementation detail: no CSL type appears in the public API.

Errors

Every failure raises a subclass of PmidToCitationError, so one except clause catches anything this library reports:

Exception Raised when
EntrezError Entrez is unreachable or reports an HTTP error
RecordNotFoundError Entrez holds no record for the requested PMID
RecordParseError A response cannot be interpreted as a MEDLINE record
CitationFormatError A record cannot be rendered in the requested style
UnknownStyleError No definition is installed for the requested style

RecordNotFoundError is an EntrezError; UnknownStyleError is a CitationFormatError.

Typing

The package ships py.typed and is checked with pyright in strict mode, so the annotations are part of the published contract.

Contributing

Contributions are welcome! See CONTRIBUTING.md for the development setup, the commit message convention, and how releases are cut.

Security

To report a vulnerability, see SECURITY.md.

Metadata

Release files for pmid-to-citation 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pmid-to-citation 0.1.1
File Size Uploaded Provenance
pmid_to_citation-0.1.1.tar.gz 120.1 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for pmid-to-citation 0.1.1
File Interpreter ABI Platform
pmid_to_citation-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 153.2 kB

Release files / pmid_to_citation-0.1.1.tar.gz

Download URL pmid_to_citation-0.1.1.tar.gz
Size 120.1 kB
Tags Source
SHA-256 checksum
How to use checksums
1765b4b245147a44839d93fdeb8d2e502a71b3a6b983ec5134ca9bfeaef68667
BLAKE2b-256 checksum
How to use checksums
2829a521e299be6b03f462737f85f6b8dff016daeb729096252027b354eca1b4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 30, 2026.

Transparency log

Release files / pmid_to_citation-0.1.1-py3-none-any.whl

Download URL pmid_to_citation-0.1.1-py3-none-any.whl
Size 33.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7a8e6bf9d26f9fff182567728c8b70103c1f22f2d920cb530cc4682ebb7162a8
BLAKE2b-256 checksum
How to use checksums
ffab852c022c83e54394bc8da77fa55153291434ae8aa4acbb60d39db37094b3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 30, 2026.

Transparency log

Security for pmid-to-citation 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for pmid_to_citation-0.1.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 30, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page