OpenAlex Scraper: Works, Authors & Institutions avatar

OpenAlex Scraper: Works, Authors & Institutions

Pricing

from $0.37 / 1,000 entity scrapeds

Go to Apify Store
OpenAlex Scraper: Works, Authors & Institutions

OpenAlex Scraper: Works, Authors & Institutions

Scrape the OpenAlex scholarly graph: works with authors, institutions, topics, citation counts, open-access status and funding. Free, unauthenticated, no proxy.

Pricing

from $0.37 / 1,000 entity scrapeds

Rating

0.0

(0)

Developer

Arman Hossain

Arman Hossain

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

OpenAlex Scraper: Works, authors, institutions, topics, citation counts, open-access status and funding from the open scholarly graph

Exports the open scholarly graph: 320M+ works with their authors, institutions, topics, citation counts, open-access status and funding, plus the author, institution, source, funder and publisher records those works link to.

OpenAlex is the open replacement for Microsoft Academic Graph. This Actor reads it directly, so there's no browser, no proxy and no authentication. Paging is handled for you, including past the offset ceiling that would otherwise cap a large result set.

Agent skill: SKILL.md

https://api.apify.com/v2/key-value-stores/t7YoTxpZEJOWvw4Ug/records/openalex-scraper.md

What you get

Every record carries the same key set regardless of entity type, so a mixed dataset still loads into one table. Fields that do not apply are null.

FieldWhat it holds
entityType, openalexId, shortId, urlWhich collection the record came from, its full OpenAlex URI and the bare ID (W2101234009)
displayName, titleEntity name, and for works the paper title
doi, landingPageUrlDOI and publisher landing page
publicationYear, publicationDate, type, language, isRetractedWork metadata
openAccessStatus, isOpenAccess, oaUrlOA colour (gold, green, bronze, hybrid, closed), flag, and free full-text URL
sourceName, sourceType, sourceIssn, hostOrganizationThe journal, repository or conference the work appeared in
authorships, authorCountAuthor name, ORCID, position, corresponding flag, affiliations and countries. Capped at the first 100 authors
institutionsDistinct affiliated institutions across all authors
concepts, topicsLegacy concepts with scores, plus the current topic, field and domain taxonomy
citedByCount, worksCount, referencedWorksCountCitation and output counts
fundingGrantsFunder name, funder ID and grant number per award
orcid, ror, countryCode, homepageUrlIdentifiers for author, institution and source records
hIndex, i10Index, twoYearMeanCitednessOpenAlex summary statistics
lastKnownInstitutionsCurrent affiliations on author records
searchQuery, updatedDate, scrapedAtWhich query produced the record, when OpenAlex last touched it, and when this run read it

RUN_SUMMARY in the key-value store holds per-run counts, the filters you used, and the outcome of every query: the ones that failed, the ones that matched nothing, and the ones skipped because the run's cap was already spent.

Use cases

  • Institutional output. Filter on a ROR ID and count works per year and topic.
  • Collaborator discovery. Pull works on a topic, then group by author and affiliation.
  • Open-access tracking. Count openAccessStatus by publisher, funder or year.
  • Systematic reviews. Run several search strings, dedupe on doi, and export to CSV for screening.
  • RAG and knowledge bases. Clean DOI-keyed metadata that joins to Crossref, PubMed and ORCID.

Quick start

One search, default cap:

{
"entityType": "works",
"searchQueries": ["large language models"]
}

Recent open-access articles across two topics, tagged per query:

{
"entityType": "works",
"searchQueries": ["crispr gene editing", "base editing"],
"filters": {
"publication_year": ">2022",
"is_oa": "true",
"type": "article"
},
"mailto": "you@example.com",
"maxResults": 1000
}

Everything one institution published last year, no free-text search at all:

{
"entityType": "works",
"filters": {
"authorships.institutions.ror": "https://ror.org/042nb2s44",
"publication_year": "2025"
},
"mailto": "you@example.com",
"maxResults": 5000
}

Input

FieldTypeDefaultNotes
entityTypestringworksworks, authors, institutions, sources, concepts, topics, funders or publishers.
searchQueriesarray[]One pass per query, results tagged with the query. Empty means a single unfiltered sweep. The same query written twice is run once.
filtersobject{}Key/value OpenAlex filter expressions, joined into one filter= parameter.
mailtostring""Contact email sent with each request, identifying you as the operator. Worth setting on large runs.
maxResultsinteger200The most records the whole run may return, across every query. Must be 1 or more — there is no unlimited value.

The Actor runs green with no input at all: it returns the first 200 works OpenAlex serves.

maxResults is the run total and the number you are billed against, never a per-query allowance. Three queries at maxResults: 300 return 300 records, not 900: the budget is split evenly across the queries and recomputed from what has actually been delivered, so a query that runs out early leaves its share to the ones after it. If the budget is spent before the last query is reached, those queries are named in RUN_SUMMARY.targetsSkipped rather than dropped silently. A record already returned by an earlier query is not returned — or charged — a second time; the count is in RUN_SUMMARY.duplicatesSkipped.

Filter values pass through untouched, so OpenAlex operators work: ">2020", "!null", "2020-2024". Array values are joined with |, which OpenAlex reads as OR, so {"type": ["article", "preprint"]} becomes type:article|preprint. An unknown filter key returns HTTP 400 and OpenAlex lists every valid field in the error, which the Actor copies into RUN_SUMMARY.failures.

Output example

{
"entityType": "works",
"openalexId": "https://openalex.org/W4404534210",
"shortId": "W4404534210",
"displayName": "A Survey on Hallucination in Large Language Models: Principles, Taxonomy, Challenges, and Open Questions",
"title": "A Survey on Hallucination in Large Language Models: Principles, Taxonomy, Challenges, and Open Questions",
"doi": "https://doi.org/10.1145/3703155",
"publicationYear": 2024,
"publicationDate": "2024-11-20",
"type": "article",
"language": "en",
"isRetracted": false,
"openAccessStatus": "bronze",
"isOpenAccess": true,
"oaUrl": "https://dl.acm.org/doi/pdf/10.1145/3703155",
"landingPageUrl": "https://doi.org/10.1145/3703155",
"sourceName": "ACM Transactions on Information Systems",
"sourceType": "journal",
"sourceIssn": "1046-8188",
"hostOrganization": null,
"authorships": [
{
"name": "Weijiang Yu",
"authorId": "A5055989750",
"orcid": "https://orcid.org/0000-0002-7449-3093",
"position": "middle",
"isCorresponding": false,
"institutions": ["Huawei Technologies (China)"],
"countries": ["CN"]
}
],
"authorCount": 11,
"institutions": ["Harbin Institute of Technology", "Huawei Technologies (China)"],
"concepts": [{ "name": "Visual Hallucination", "level": 2, "score": 0.564 }],
"topics": [
{ "name": "Topic Modeling", "field": "Computer Science", "domain": "Physical Sciences", "score": 0.9926 }
],
"citedByCount": 1757,
"referencedWorksCount": 214,
"fundingGrants": [],
"updatedDate": "2026-08-05T07:39:15.569665",
"url": "https://openalex.org/W4404534210",
"searchQuery": "large language models",
"scrapedAt": "2026-08-06T11:43:13.229Z"
}

An authors record fills a different subset: worksCount, hIndex, i10Index, twoYearMeanCitedness, lastKnownInstitutions, and a topics list where each entry carries a works count rather than a relevance score.

Writing filters

Filters are where the real power is. A few that come up constantly:

GoalFilter
Works from one institution{"authorships.institutions.ror": "https://ror.org/042nb2s44"}
Works by one author{"author.orcid": "https://orcid.org/0000-0002-7449-3093"}
Published since 2022{"publication_year": ">2021"}
Journal articles only{"type": "article"}
Open access only{"is_oa": "true"}
In one journal{"primary_location.source.issn": "1046-8188"}
Highly cited{"cited_by_count": ">100"}
Funded by NSF{"awards.funder_id": "F4320306076"}

To find an institution's ROR or a funder's OpenAlex ID, run the Actor once with entityType: "institutions" or "funders" and a search query. The ror and shortId fields it returns are exactly what the filters above expect.

API example

curl -X POST "https://api.apify.com/v2/acts/arman-bd~openalex-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"entityType": "works",
"searchQueries": ["retrieval augmented generation"],
"filters": { "publication_year": ">2023", "is_oa": "true" },
"mailto": "you@example.com",
"maxResults": 500
}'

JavaScript example

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('arman-bd/openalex-scraper').call({
entityType: 'works',
filters: { 'authorships.institutions.ror': 'https://ror.org/042nb2s44', publication_year: '2025' },
mailto: 'you@example.com',
maxResults: 2000,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
const oaShare = items.filter((w) => w.isOpenAccess).length / items.length;
console.log(`${items.length} works, ${(oaShare * 100).toFixed(1)}% open access`);

Notes

  • Paging is always cursor-based. Every query starts at cursor=* and follows meta.next_cursor. Offset paging silently caps at 10,000 records and cursor paging does not, so maxResults is the only limit that applies.
  • Each request returns 200 records, which is OpenAlex's maximum. A 5,000-record query is 25 requests.
  • Setting mailto is worth it on large runs. Your address is sent with each request and carried in the User-Agent, which is what the OpenAlex docs ask of automated clients.
  • Author lists are capped at 100. Some consortium papers list thousands of authors, and authorCount always reports the true total.
  • One bad query won't kill the run. A 400 or 404 is recorded in RUN_SUMMARY.failures and the remaining queries continue, delivering their records as normal. The Actor throws only when every query failed and nothing was returned.
  • A query that matched nothing is named too, in RUN_SUMMARY.emptyQueries, with its match count in RUN_SUMMARY.queries[]. Zero rows from a query you ran and zero rows from a query that was never reached look identical in a dataset; the summary is what tells them apart.
  • The cap is checked before anything is fetched. maxResults below 1, fractional or unreadable stops the run immediately with an error naming the field, rather than being read as "no limit" — nothing is fetched and nothing is charged.
  • Transient errors get retried. A throttled or 5xx response is retried up to three times with growing backoff, honouring the wait the response asks for up to a 30-second ceiling, and each request has a 60-second timeout because a full 200-record page can take ten seconds or more. A request the source rejects outright, and a payload that is not the expected shape, are final for that query and are recorded rather than retried.

FAQ

Do I need an API key? No. You supply no credentials.

Do I need a proxy? No. Proxy configuration is not required to run this Actor.

How many records can one run return? Exactly as many as you set maxResults to, across all queries together — that is the number you are billed against. Cursor paging has no ceiling, so multi-hundred-thousand-record exports are a matter of run time and the cap you set, not API limits.

Can I get abstracts? OpenAlex ships abstracts as an inverted index rather than text, and licensing varies by source, so this Actor does not emit them. Use oaUrl or landingPageUrl to fetch the full text where it is openly available.

Concepts or topics? Topics are the current taxonomy (topic, then subfield, field and domain) and are what OpenAlex maintains. Concepts are the legacy Microsoft Academic Graph vocabulary, kept for continuity. Both are returned for works.

Can I schedule it? Yes. Diff on openalexId plus updatedDate to pick up only records OpenAlex has revised since the last run.