8 Free Research Paper APIs With No Key (2026)
On July 9, 2026 I asked arXiv for one paper about large language models. It answered HTTP 200. My parser took the response, found nothing useful, and moved on without raising a thing. The body was not corrupt. It just was not JSON.
arXiv, the preprint server that carries most of the modern machine-learning literature, replies in Atom XML: <?xml version="1.0"?><feed>.... Run json.loads() on that and you get a JSONDecodeError, or, if the call sits inside a lazy try/except, you get nothing and the code shrugs. Ten seconds of trusting the status line and an empty result goes straight into your index as if the paper never existed.
That is the whole post. Finding a free research-paper API is the easy ten percent. The hard part: each one returns a clean 200 and something subtly wrong, and it does it a different way on almost every endpoint.
A free research-paper API here means a public scholarly-metadata endpoint (papers, DOIs, citations, open-access PDFs) that answers with no API key, no signup, and no card. Not a bulk data dump, not a partner agreement, not a portal that wants your institutional login. A real REST call you can paste into a terminal right now. I found eight that clear that bar. I re-verified each one with a live curl on July 9, 2026: real HTTP code, real body, trimmed but never paraphrased. If you build a RAG index over papers, a citation tool, or an agent that reads the literature, these are the lookups you reach for. Every one of them can hand you a 200 that lies.
Here is the finding before the list. This is not one engine wearing eight hats, which is what most keyless roundups turn out to be. These are eight separate organizations: Cornell runs arXiv, two nonprofit DOI registrars run Crossref and DataCite, OurResearch runs OpenAlex and Unpaywall, CERN runs Zenodo, and DOAJ and OpenCitations are their own nonprofits. That spread is the trap. Eight orgs means eight response shapes: Atom XML, a JSON:API bracket dialect, a bare array with no envelope, a Solr error body wearing a 200. You cannot write one parser and aim it at all of them. What they share is not code. It is a single failure mode: a 200 that is empty, fuzzy, or the wrong entity, almost never an honest 500.
Let me be straight about scope, because this is where roundups usually stretch. Full disclosure: I have not run these scholarly APIs in production. My numbers come from a different domain (2,190 scraper runs, including 962 on a single Trustpilot scraper), and I cite them for exactly one lesson those runs beat into me: parse the payload, do not trust the status code. Every trimmed body below is from a live curl on July 9, 2026, not from operating these services at scale. Where a keyless window looks shaky, I flag it instead of selling it.
Here is the full set at a glance.
| # | API | What it answers | Example call | No key? |
|---|---|---|---|---|
| 1 | arXiv | Preprint search (physics, CS, math) | GET export.arxiv.org/api/query?search_query=... | Yes |
| 2 | Crossref | DOI metadata for journal articles, books | GET api.crossref.org/works?query=... | Yes |
| 3 | OpenAlex | Works, authors, institutions graph | GET api.openalex.org/works?search=... | Yes |
| 4 | DataCite | DOIs for datasets, software, preprints | GET api.datacite.org/dois?query=... | Yes |
| 5 | Unpaywall | DOI to legal open-access PDF | GET api.unpaywall.org/v2/<doi>?email=... | Yes* |
| 6 | DOAJ | Articles in open-access journals | GET doaj.org/api/v3/search/articles/... | Yes |
| 7 | OpenCitations | Citation graph by DOI | GET opencitations.net/index/api/v2/references/doi:... | Yes |
| 8 | Zenodo | CERN research-output repository | GET zenodo.org/api/records?q=... | Yes |
*Unpaywall needs an email= parameter in the query. It is not a secret key, but it is not optional either: drop it and you get a 422, not a 200. Three more names people search for (Semantic Scholar, CORE, and HAL) look keyless and are not, and they get an honest section near the end.
Full-text search, where fuzzy is the real trap
The first three are the ones you reach for to find a paper by words. All three share the same quiet lie: the count looks like a hit, and the top row may not be your paper.
1. arXiv: a 200 that is not even JSON
arXiv is the preprint server for physics, math, computer science, and most of the ML field. Its API takes a search_query and returns results as Atom XML, not JSON. That single fact is the most common way people break an arXiv integration.
# runnable, read-only
curl "https://export.arxiv.org/api/query?search_query=all:large+language+models&max_results=1"
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>ArXiv Query: search_query=all:large language models</title>
<opensearch:totalResults>...</opensearch:totalResults>
<entry><title>...</title> ... </entry>
</feed>
HTTP 200, content-type: application/atom+xml. There is no JSON mode. Parse it with feedparser or an XML library, not json.loads. The miss case is quieter still: search for something that matches nothing and arXiv returns another 200 with an empty <feed> and <opensearch:totalResults>0</opensearch:totalResults>. No entries, no error. The signal that you found something is totalResults, not the HTTP code. One small transport trap: http://export.arxiv.org answers 301 to the https:// host, so start with https or your first request is a redirect you have to follow. Docs at info.arxiv.org/help/api.
When to use it: preprint discovery in physics, CS, and math, once your client speaks Atom XML and reads totalResults.
2. Crossref: the count says millions, the top hit may not be yours
Crossref is the nonprofit DOI registrar behind a large share of the world’s journal articles and books. Its REST API is keyless and returns clean JSON.
# runnable, read-only
curl "https://api.crossref.org/works?query=large+language+models&rows=1"
{"status":"ok",
"message":{"total-results":3142373,
"items":[{"publisher":"The MIT Press", ... }]}}
total-results reads 3,142,373 for that query on July 9, 2026, a live counter that ticks up while you read this, so treat the exact digits as a snapshot. It looks like Crossref nailed your paper. It did not necessarily. query= is a fuzzy full-text match ranked by relevance, and items[0] is the best guess, not your specific work. If you paste in a title and grab the first item, you can silently attach the wrong DOI to a citation. Resolve the exact paper by DOI, or by matching precise fields and the returned score, not by trusting position zero. A query that matches nothing returns a normal 200 with total-results: 0 and items: [], again not an error. (An empty query= does the opposite: it matches the whole ~184M-work corpus, so “typed nothing” and “found nothing” are not the same call.)
There is a second, invisible cost. Crossref runs a polite pool and an anonymous pool. Send a mailto (in the query, or a descriptive User-Agent) and you land in the polite pool with more stable service. Skip it and you sit in the anonymous pool that gets throttled first when the service is busy. This is the same lesson MusicBrainz once taught me with a hard 403 on a missing User-Agent: identifying yourself is not politeness, it is data hygiene. Docs at api.crossref.org/swagger-ui.
When to use it: DOI and bibliographic metadata for published literature, with a mailto and exact-match resolution instead of a blind items[0].
3. OpenAlex: pagination that caps at 10,000 (with a loud 400)
OpenAlex, from the nonprofit OurResearch, is the open replacement for Microsoft Academic Graph: works, authors, institutions, and venues, all linked. Keyless JSON, and it honors a polite pool via mailto too.
# runnable, read-only
curl "https://api.openalex.org/works?search=large+language+models&per-page=1&mailto=you@example.com"
{"meta":{"count":3780168,"page":1,"per_page":1, ... },
"results":[ ... ]}
count is 3,780,168 for that search on July 9. Here is the trap that bites at scale: classic page= pagination is capped at 10,000 records. Ask for page 201 at 50 per page and you get an HTTP 400 with Maximum results size of 10,000 records is exceeded. Cursor pagination is required. Credit where it is due, that is an honest error, not a lying 200, the one spot on this list where the API fails loudly instead of quietly. To walk a full result set you switch to cursor pagination (cursor=*, then follow meta.next_cursor). The search parameter is full-text and fuzzy, same caveat as Crossref: the top result is a candidate, not a confirmed match. And, again, no mailto means the anonymous pool and rougher throttling. Docs at docs.openalex.org.
When to use it: building a citation or author graph, with cursor pagination and a mailto, not page= past 10k.
Datasets, open-access PDFs, and OA journals
The next three narrow from “find any paper” to specific jobs: a dataset DOI, a free PDF, a vetted open-access article. The trap shifts from fuzzy matching to coverage: an empty result means “we do not index this,” not “it does not exist.”
4. DataCite: the bracket parameter that breaks your URL builder
DataCite is the other big nonprofit DOI registrar. Its DOIs point at datasets, software, and preprints rather than journal articles. Keyless JSON, JSON:API style.
# runnable, read-only (note the encoded brackets)
curl "https://api.datacite.org/dois?query=climate&page%5Bsize%5D=1"
{"data":[{"id":"10.5281/zenodo.21271391","type":"dois", ... }]}
The result is fine. Getting there is the trap. DataCite uses JSON:API bracket parameters like page[size], and a raw [ in a URL breaks naive builders. curl itself refuses it with curl: (3) bad range in URL position .... You have to URL-encode the brackets as %5B%5D, so page[size]=1 becomes page%5Bsize%5D=1. Skip that and your request never leaves the client, or your HTTP library mangles it. On a miss the response is a plain 200 with data: [], which brings up the coverage point that runs through this whole middle section: an empty data array means DataCite has not indexed it, not that the thing does not exist. Docs at support.datacite.org.
When to use it: finding DOIs for datasets and software, with the bracket params URL-encoded.
5. Unpaywall: a 200 with best_oa_location: null is not a free PDF
Unpaywall (also OurResearch) does one job: given a DOI, it tells you whether a legal open-access copy exists and where. It is keyless, but it requires an email parameter.
# runnable, read-only -- swap in YOUR real email; example.com is rejected with a 422
curl "https://api.unpaywall.org/v2/10.1038/nature12373?email=you@example.com"
{"best_oa_location":{"host_type":"repository",
"url":"https://arxiv.org/pdf/1304.106..."},
"is_oa":true, ... }
Two traps. First, the email is not optional: drop it and you get a 422, not a 200, and a throwaway like example.com is rejected with a 422 too, so it has to be a real address. This is “keyless” only in the sense that the email is not a secret. Second, and quieter: a paywalled article returns a perfectly valid 200 with "best_oa_location": null. The request succeeded; there is simply no free PDF. Code that does resp.json()["best_oa_location"]["url"] throws a TypeError on null, on a 200. Check is_oa and the null before you dereference. One honest note: Unpaywall is now in maintenance, and OurResearch steers new integrations to OpenAlex, which absorbed its open-access data. It still answers today; I would not build something new solely on it. Docs at unpaywall.org/products/api.
When to use it: turning a DOI into an open-access PDF link, with a null guard and OpenAlex as the longer-term home.
6. DOAJ: total: 0 means “not in an OA journal we index,” not “no such paper”
DOAJ, the Directory of Open Access Journals, indexes articles, but only from journals it has vetted as fully open access. Keyless v3 JSON API.
# runnable, read-only
curl "https://doaj.org/api/v3/search/articles/machine%20learning?pageSize=1"
{"total":189602,"page":1,
"results":[{"bibjson":{"identifier":[
{"id":"10.46481/...","type":"doi"}, ... ]}}]}
total is 189,602 for that query on July 9, a live count that drifts run to run, so read the exact number as a July 9 snapshot. The trap is the shape of the corpus, not the response. DOAJ covers only declared open-access journals, so a total: 0 is a coverage gap, not proof the paper does not exist. The paper may sit in a hybrid or closed journal DOAJ deliberately does not index. Use DOAJ to confirm something is in a vetted OA venue; do not use an empty result to conclude a work is missing from the literature. Docs at doaj.org/api/v3/docs.
When to use it: filtering for genuinely open-access journal articles, never as a completeness check on all literature.
Citation graphs and research repositories
The last two are less about finding a paper and more about what surrounds it: who cites it, and what artifacts were deposited. Same 200-that-lies theme, two new shapes.
7. OpenCitations: an empty array is “not indexed,” and every ID is four IDs
OpenCitations is a nonprofit that publishes open citation data (who cites whom, keyed by DOI). Its v2 API returns a bare JSON array.
# runnable, read-only
curl "https://api.opencitations.net/index/v2/references/doi:10.1186/s13643-016-0384-4"
[{"oci":"061402590389-061901516871",
"citing":"omid:br/... doi:10.1186/... openalex:W2560438049 pmid:27919275",
"cited":"..."}]
Two things to notice. First, an empty [] means OpenCitations has not indexed those citations, not that the paper has zero citations. Coverage again, dressed as absence. Second, look at that citing value: it is a single space-separated string carrying four identifiers at once, an OMID, a DOI, an OpenAlex ID, and a PubMed ID, all for the same work. That is the entity-resolution problem made literal. Split on space and treat each token as a separate paper and you have quadrupled your node count with phantom duplicates. Parse the prefixes (omid:, doi:, openalex:, pmid:) and collapse them to one entity. Small transport note: the older opencitations.net/index/api/v2/... path 301-redirects to the canonical host api.opencitations.net/index/v2/... (the one above), and the http:// form 301s too, so call the canonical host directly or let your client follow redirects. Docs at opencitations.net/index/api/v2.
When to use it: open citation-graph edges by DOI, with prefix-aware ID parsing and empty-array-means-uncovered handling.
8. Zenodo: same paper, many versions, one concept
Zenodo is CERN’s general-purpose repository for research outputs: datasets, software, posters, and papers, each with a minted DOI. Keyless JSON search.
# runnable, read-only
curl "https://zenodo.org/api/records?q=machine+learning&size=1"
{"hits":{"hits":[{"id":13235113,
"conceptrecid":"13235112",
"doi":"10.5281/zenodo.13235113", ... }]}}
Note the double-nested hits.hits envelope: a Solr/Elasticsearch tell, and a different shape from every other entry on this list, which is the whole diversity problem in one field path. Two real traps. Records are versioned: one logical upload has many id values that all share a single conceptrecid. If you index search results without collapsing on conceptrecid, the same dataset shows up three times in your top-k as if the versions were different works. And Zenodo rate-limits harder than it looks: the live response carries x-ratelimit-limit: 30 with retry-after: 60, so anonymous clients get about 30 requests a minute before a 429. Keyless is not the same as unlimited. Docs at developers.zenodo.org.
When to use it: searching research artifacts and software, deduplicated by conceptrecid, with backoff for the 429.
The three that look keyless and are not (and one honorable mention)
Three APIs kept surfacing when I searched for “free research paper API,” and all three lie about being keyless in a different way. Naming them is part of keeping this honest.
Semantic Scholar (from the Allen Institute for AI) has a good graph API and a keyless “shared pool.” On July 9 that pool answered me with a 429 on the first request:
curl "https://api.semanticscholar.org/graph/v1/paper/search?query=large+language+models&limit=1&fields=title,year"
{"message":"Too Many Requests. ... apply for a key ...","code":"429"}
The "code":"429" sits in the JSON body while the transport is also 429, so at least it is consistent. But the shared keyless pool is congested enough that you cannot rely on it. For anything real, request a free key and add backoff.
CORE (Open University, UK) aggregates open-access full text and, on July 9, actually returned a keyless 200 after a 301 to a trailing slash:
{"totalHits":592803,"limit":1,
"results":[{"authors":[{"name":"van Rijn J.N."}, ... ]}]}
totalHits was 592,803, so it works keyless today. But CORE’s own docs ask for a Bearer key and it throttles hard, so the keyless window is a courtesy that can close without notice. Do not build on it. (For the record: the “301” here is a redirect to a trailing slash, not a key wall. Worth knowing before you assume you are being blocked.)
HAL (the French national open archive) is the cleanest example of “200 lies” I hit all day. Every form of the query I tried, from our datacenter IP, returned HTTP 200 with an error body:
curl "https://api.archives-ouvertes.fr/search/?q=deep&rows=1&wt=json"
{"error":{"msg":"Error. See help : /docs"}}
HTTP 200, and the body is nothing but an error object. I tried three query shapes and got the same error each time, which smells like an API change or an IP filter on datacenter ranges. I did not get a working data call out of HAL today, so I am putting it here honestly rather than pretending it is a clean entry. If you can reach it from a residential or institutional IP, treat that 200 as meaningless and check for an error key first.
Honorable mention, bioRxiv. For life-sciences preprints, bioRxiv’s API returned a clean keyless 200:
{"messages":[{"status":"ok","count":30,"total":"141"}],
"collection":[{"title":"MVA Vector Vaccines ..."}]}
It is genuinely keyless and useful. I left it out of the main eight for two reasons: it is a single-discipline preprint server, not a cross-publisher index, and it sits in a biomedical area distinct from the general scholarly layer these eight cover. Even here it plants a type trap worth noting: count is the number 30 while total is the string "141" in the same object, so cast before you compare. Docs at api.biorxiv.org.
Why the paid giants are not here
The roundup stays honest by naming what it skips. Scopus (Elsevier), Web of Science (Clarivate), and Dimensions (Digital Science) are the big commercial scholarly databases, and every one of them wants an API key tied to a subscription or an approved account. Good coverage, real money, institutional contracts. Exactly the paid tier this list exists to route around, not entries in it. If your employer already pays for one, use it. If you are building on your own, the eight above are your layer.
Parse the payload, not the status code
Finding the endpoint is ten percent of the work. Here is the ninety percent, pulled straight from the failures above.
Check the content-type before you parse. arXiv hands you Atom XML on a 200; HAL hands you an error object on a 200. A blind resp.json() either throws or, worse, a lazy try/except swallows it and you index nothing. Assert application/json first, and look for an error key second.
Assert on a body count, not the HTTP code. Crossref’s no-match query, DataCite’s data: [], DOAJ’s total: 0, and OpenCitations’ [] are all 200s. And every one can mean “we do not index this,” not “it does not exist.” Read the count or total field and treat zero as a coverage gap you might fill from a second source.
Treat the top search hit as a candidate, not your paper. query= and search= on Crossref, OpenAlex, and DataCite are fuzzy full-text ranking. items[0] is a guess. For the exact work, resolve by DOI or match precise fields and the returned score. It is the same one-entity-many-IDs problem OpenCitations shows you outright.
Send a real mailto and User-Agent. Crossref, OpenAlex, and Unpaywall all reward an identified client with the polite pool and punish anonymous callers with the first throttle. No key does not mean no etiquette.
Assume keyless windows drift. CORE answers keyless today and officially wants a key; Semantic Scholar’s shared pool is already handing out 429s; Zenodo’s live x-ratelimit-limit header caps you near 30 per minute. “Free and no key” is a snapshot from July 9, 2026, not a warranty.
Here is a guard that folds the first four checks into one function.
# runnable local -- validate content-type and body, not just the status code
import requests
def openalex_top(query, email="you@example.com"):
r = requests.get(
"https://api.openalex.org/works",
params={"search": query, "per-page": 1, "mailto": email},
headers={"User-Agent": f"my-research-tool/1.0 (mailto:{email})"},
timeout=15,
)
r.raise_for_status() # honest 4xx/5xx, NOT a 200 with an error body
if "application/json" not in r.headers.get("content-type", ""):
return None # arXiv-style XML / HAL-style bodies stop here
body = r.json()
if isinstance(body, dict) and "error" in body:
return None # HAL returns 200 + {"error": ...}
if body.get("meta", {}).get("count", 0) == 0:
return None # 200 + empty = coverage gap, not a match
return body["results"][0] # a CANDIDATE -- still verify before trusting
print(openalex_top("large language models")) # -> a record
print(openalex_top("asdfqwer no such work zxcv")) # -> None, no crash
raise_for_status catches the honest failures. The content-type line catches arXiv and HAL. The error-key line catches HAL’s 200. The count line catches the empty coverage gaps. What it deliberately does not do is trust results[0] as your exact paper. That last check is yours to write, because only you know which work you meant.
For context, not a claim of scale: I build web-scraping and data-enrichment tool layers, currently 2,190 runs across 32 actors in production, and the output is always a table of rows that need trustworthy enrichment columns. Company identity was one keyless column. Nutrition was another. Scholarly metadata is this one. Same keyless, no-card layer, different question, and the same failure mode every time: a 200 that is empty, fuzzy, or the wrong entity, almost never an honest 500.
FAQ
Are research paper APIs really free with no key?
Yes. arXiv, Crossref, OpenAlex, DataCite, Unpaywall (with an email parameter), DOAJ, OpenCitations, and Zenodo all return metadata with no API key and no signup. The big commercial databases (Scopus, Web of Science, Dimensions) require a paid key. Semantic Scholar and CORE technically have keyless pools but throttle hard and officially want a key, so they are labeled honestly rather than listed.
Why does arXiv return XML instead of JSON?
arXiv’s API predates the JSON-everywhere era and returns Atom XML (content-type: application/atom+xml) with no JSON mode. Parse it with a feed or XML parser, not json.loads, and read <opensearch:totalResults> to tell a hit from a miss, because a no-match query still returns HTTP 200 with an empty <feed>.
What is the difference between Crossref and OpenAlex? Crossref is the DOI registrar: authoritative bibliographic metadata for registered works. OpenAlex is a graph built on top of Crossref and other sources, adding authors, institutions, and citation links. For a canonical DOI record, use Crossref; for a connected graph of works and authors, use OpenAlex. Both run fuzzy full-text search, so neither guarantees the top result is your exact paper.
Why does a scholarly API return millions of results but not my paper?
Because query= and search= are relevance-ranked full-text matching, not exact lookup. A total-results of 3,142,373 (Crossref) or a count of 3,780,168 (OpenAlex) on July 9, 2026 describes the whole fuzzy match set; items[0] is the best guess. Resolve the exact work by DOI, or by matching precise fields and the returned score.
Which free API gives open-access PDF links?
Unpaywall: pass a DOI and your email, and it returns best_oa_location with a legal open-access URL when one exists. A paywalled paper returns HTTP 200 with best_oa_location: null, so check is_oa and guard the null before you read .url.
Do these free APIs have rate limits?
Yes, keyless is not unlimited. Zenodo caps anonymous clients near 30 requests per minute (its live x-ratelimit-limit: 30 header) before a 429; Semantic Scholar’s shared keyless pool was already returning 429 on July 9, 2026; Crossref and OpenAlex run a polite pool that gives identified clients (a mailto) more stable service than anonymous ones. For steady load, send a real User-Agent with contact info and add backoff.
Written by Aleksei Spinov. I build web-scraping and data-enrichment tool layers, currently 2,190 runs across 32 actors in production. Every API above was re-verified with a live curl (real HTTP code, real body) on July 9, 2026 before publishing; responses are trimmed, not paraphrased. I have not run these scholarly APIs in production; the 2,190 runs are a different domain, cited only for the parse-the-body pattern. Drafted with an AI assistant, then fact-checked and edited by me against the raw responses.
Follow for the next keyless API layer I test. And tell me: which scholarly or research API has quietly handed you a clean 200 with the wrong body (arXiv’s XML, a fuzzy top hit, an empty coverage gap), and which field finally gave the bug away? I read every comment.
More production scraping tips: t.me/scraping_ai