Europe PMC Scraper
Pricing
from $1.40 / 1,000 results
Europe PMC Scraper
Search Europe PMC, the superset of PubMed: 43M+ abstracts, 10M+ open-access full-text articles, preprints (bioRxiv/medRxiv), patents and theses. Lucene query plus filters, cursor pagination with no ceiling, lookup by PMID/PMCID/DOI, citation networks, text-mined annotations. Keyless.
Pricing
from $1.40 / 1,000 results
Rating
0.0
(0)
Developer
Ibnu Adzim
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Europe PMC Scraper (Biomedical Papers, Preprints, Citations)
Search Europe PMC — the superset of PubMed.
43M+ abstracts (MED, i.e. PubMed/MEDLINE), 10M+ open-access full-text
articles (PMC), preprints from bioRxiv and medRxiv (PPR), plus
patents, Agricola, Chinese biomedical, theses and the NCBI bookshelf. No key,
no login, HTTP-only.
Companion to pubmed-articles-scraper (PubMed only), openalex-scholar-scraper
(works), crossref-works-scraper (articles) and datacite-scraper (datasets
and software).
search— a Lucenequeryand/or structured filters (sources, author, journal, publication type, year range, open access, full text in Europe PMC, has-abstract). Cursor-paginated — no result ceiling.articles— look up specific articles by PMID (23000000), source-qualified id (MED:23000000,PMC:PMC3531190,PPR:PPR1303040) or DOI → the fullcorerecord each.citation-network— walk an article's citations forwards (citing— who cites it) or backwards (cited— its reference list).
Set includeAnnotations to attach Europe PMC's text-mined annotation
layer — genes/proteins, diseases, chemicals, organisms, cell types,
accession numbers, extracted from the full text.
| Record type | One per | Carries |
|---|---|---|
SEARCH_SUMMARY | search / citation walk | composed query, hitCount, resultsReturned, pagesFetched, requestsMade, duplicatesSkipped, truncated |
ARTICLE | article | id, source, pmid, pmcid, doi, title, abstract, authors (+ ORCID + affiliation), journal, pubYear, citedByCount, isOpenAccess, license, meshTerms, chemicals, keywords, grants, fullTextUrls, textMinedAnnotations, europepmcUrl |
ERROR | bad input / missing article | _error + _errorDetail |
Every ARTICLE row carries the verbatim Europe PMC record in raw (drop with
slimOutput).
Things this API will mislead you about
Each is measured, and each has a scenario in
tests/smoke/europepmc-scraper_traps.sh (10/10 passing).
⭐ The citation endpoints page by page and pageSize — and page indexes
pages of the size you asked for. Shrinking pageSize on the last page to
avoid over-fetching silently re-serves rows you already have:
page=1&pageSize=100 then page=2&pageSize=50 returns rows 51–100 a second
time, HTTP 200 throughout, with no duplicate signal anywhere in the response.
Measured 2026-08-29 — 150 rows of which only 100 were unique. This Actor holds
pageSize constant for the whole walk, trims at the end, and reports
duplicatesSkipped so any future reshuffle is visible rather than silent.
Every response is HTTP 200 — a malformed query, a gibberish query and a
non-existent article all answer 200. There is no "bad query" signal, so a
zero-hit search is reported as a SEARCH_SUMMARY with hitCount: 0, never as
an error, and an empty run stays distinguishable from a failed one.
An unknown SRC returns zero hits, silently. sources is validated
against Europe PMC's controlled list up front rather than becoming a mystery
empty result.
/search has no page parameter — deep paging is cursorMark only
(*, then nextCursorMark). pageSize maxes at 1000; asking for 1001
returns 200 with an empty result list.
There is no /article/<id> endpoint. A single article is looked up
through search?query=EXT_ID:<id> AND SRC:<src> (or DOI:<doi>), which is
why a missing article is an empty result list rather than a 404.
A DOI has no citation endpoint. citation-network needs a PMID / MED: /
PMC: id; a DOI is rejected before any request instead of returning nothing.
The list fields are {singular: [...]} wrappers that can each be null —
meshHeadingList.meshHeading[], grantsList.grant[], chemicalList.chemical[],
keywordList.keyword[], authorList.author[], fullTextUrlList.fullTextUrl[],
pubTypeList.pubType[]. All are unwrapped to plain lists.
isOpenAccess / inEPMC / hasPDF are the strings "Y" / "N", not
booleans. Normalised to real booleans.
id is source-specific — a MED record's id is its PMID, a PMC
record's is its PMCID, a PPR record's is PPR…. pmid / pmcid / doi
are separate fields, and any of them can be absent.
citations / references rows are lean — title, authors, year, journal
abbreviation, id, source, cited-by count. No abstract. Feed the ids back
through articles mode if you need the full records.
Notes on cost
search: one request per 100 rows (cursor pages). articles: one request per
article, plus one more each if includeAnnotations is on. citation-network:
one request per 100 linked articles. resultType: "lite" returns a much
smaller row when you only need bibliographic fields. Europe PMC has no
anti-bot layer, so no proxy is needed — the default is off.
Policy
www.ebi.ac.uk/robots.txt allows /europepmc/webservices/rest/…. No key, no
login, no authenticated surface is touched. Europe PMC content is a mix of
licences — each row's isOpenAccess and license say which.