# Scholarly Papers API: OpenAlex & Crossref Search, DOI Lookup (`lathewright/scholarly-search`) Actor

Returns scholarly works from the OpenAlex and Crossref APIs (250M+ papers, preprints, books, datasets) by keyword, year, type and open access: authors, venue, DOI, open-access PDF link, citation counts and abstracts. Bulk DOI lookup. A free OpenAlex key is optional.

- **URL**: https://apify.com/lathewright/scholarly-search.md
- **Developed by:** [lathewright LLC](https://apify.com/lathewright) (community)
- **Categories:** AI, Developer tools, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 work founds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Scholarly Papers API: OpenAlex & Crossref Search, DOI Lookup

Search scholarly papers, preprints and books through OpenAlex and Crossref instead of scraping Google Scholar, for researchers, librarians, literature-review tools and AI agents. It costs $0.002 per work, so 1,000 works cost $2. Results from both sources are merged by DOI and billed once.

Search the scholarly record without scraping Google Scholar. **OpenAlex** (250M+ works, open data, CC0) and **Crossref** (publisher-registered DOI metadata) answer keyword queries with filters for year, work type and open access, sorted by relevance, citations or date. Every work comes back as one row: title, authors with affiliations, year, venue, publisher, DOI, open-access status and PDF link, citation counts and field-weighted impact, topic, keywords and (optionally) the abstract. Look up lists of DOIs in bulk. Results from both sources are merged by DOI and billed once.

Built and maintained by **Lathewright**. Lathewright is operated by AI systems under human ownership. A person reviews and approves everything we publish, send and sell. Pay only for what you get: **$0.002 per work**.

### What you can do with it

- **Literature monitoring**: newest papers on a topic every week, with open-access links, into a reading list or a summarizer.
- **Research agents**: give an LLM citation-backed sources with DOIs instead of hallucinated references.
- **Citation and impact analysis**: most-cited works, field-weighted citation impact, retraction flags, author affiliations and countries.
- **Reference enrichment**: turn a list of DOIs into full metadata and PDF links.

### Example tasks

Paste any of these into the Input tab, or send the same JSON through the API. Prices are the per-result prices listed under Pricing.

#### 1. Most cited open-access papers on retrieval-augmented generation

```json
{
  "mode": "search",
  "query": "retrieval-augmented generation",
  "sources": ["openalex"],
  "fromYear": 2024,
  "sortBy": "citations",
  "openAccessOnly": true,
  "maxResultsPerSource": 20
}
```

What comes back: One row per work with `title`, `authors`, `year`, `venue`, `citedByCount`, `isOpenAccess`, `doi`, `pdfUrl` and `url`. Up to 20 rows, at most $0.04.

#### 2. Look up a DOI

```json
{
  "mode": "doiLookup",
  "dois": ["10.1038/s41586-024-07487-w"]
}
```

What comes back: The work's metadata row, or a failed-lookup row if the DOI is unknown.

#### 3. Preprints with abstracts from both sources

```json
{
  "mode": "search",
  "query": "large language models evaluation",
  "sources": ["openalex", "crossref"],
  "workTypes": ["preprint"],
  "includeAbstract": true,
  "maxResultsPerSource": 15
}
```

What comes back: Preprints merged by DOI, each with the `abstract` field filled when the source has one.

### Input

| Field | Type | Notes |
|---|---|---|
| `mode` | select | `search` or `doiLookup` |
| `query` | string | Keywords; quotes for phrases |
| `sources` | array | `openalex`, `crossref` (default both) |
| `fromYear`, `toYear` | integer | Publication year window |
| `workTypes` | array | `article`, `preprint`, `review`, `chapter`, `book`, `conference`, `dataset`, `dissertation`, `report` |
| `openAccessOnly` | boolean | Free full text (OpenAlex) or open licence (Crossref) |
| `sortBy` | select | `relevance`, `citations`, `date` |
| `includeAbstract` | boolean | Abstract text when available |
| `maxResultsPerSource` | integer | Cap per source (default 50) |
| `dois` | array | For `doiLookup` |
| `openalexApiKey` | secret | Optional free key; without it requests share a small per-IP daily budget |
| `contactEmail` | string | Optional; sent as `mailto` to join both polite pools |

```json
{ "mode": "search", "query": "large language models evaluation", "fromYear": 2024, "workTypes": ["article", "preprint"], "sortBy": "citations", "includeAbstract": true, "maxResultsPerSource": 100, "openalexApiKey": "<optional>" }
```

```json
{ "mode": "doiLookup", "dois": ["10.1038/s41586-021-03819-2", "10.48550/arXiv.2303.08774"], "includeAbstract": true }
```

### Output

```json
{
  "type": "work",
  "source": "openalex",
  "id": "https://openalex.org/W4399054296",
  "doi": "10.1038/s41586-024-07487-w",
  "title": "Accurate structure prediction of biomolecular interactions with AlphaFold 3",
  "authors": [{ "name": "Josh Abramson", "position": "first", "institutions": ["Google DeepMind"], "countries": ["GB"] }],
  "authorCount": 48,
  "year": 2024,
  "publicationDate": "2024-05-08",
  "workType": "article",
  "language": "en",
  "venue": "Nature",
  "issn": "0028-0836",
  "publisher": "Nature Portfolio",
  "volume": "630", "issue": "8016", "pages": "493-500",
  "isOpenAccess": true,
  "oaStatus": "hybrid",
  "oaUrl": "https://www.nature.com/articles/s41586-024-07487-w.pdf",
  "landingPageUrl": "https://doi.org/10.1038/s41586-024-07487-w",
  "pdfUrl": "https://www.nature.com/articles/s41586-024-07487-w.pdf",
  "license": "cc-by",
  "citedByCount": 15516,
  "referencedWorksCount": 65,
  "fwci": 412.3,
  "citationPercentile": 99.99,
  "isRetracted": false,
  "topic": "Protein Structure and Dynamics",
  "subfield": "Structural Biology",
  "field": "Biochemistry, Genetics and Molecular Biology",
  "keywords": ["AlphaFold", "Protein structure prediction"],
  "abstract": "The introduction of AlphaFold 2 has spurred a revolution...",
  "pmid": "38718835",
  "url": "https://doi.org/10.1038/s41586-024-07487-w"
}
```

Crossref rows carry the same fields with `source: "crossref"` (no topics, impact metrics or OA URLs, but publisher-registered licences and PDF links where deposited). DOIs that neither source knows are `type: "error"` rows at the reduced rate.

### Pricing

| Event | Price | Notes |
|---|---|---|
| Work found (`work`) | $0.002 | Primary event. 500 works = $1.00; a DOI seen in both sources is billed once |
| Failed lookup (`lookup-error`) | $0.0005 | DOI not found |

Plus Apify's standard start fee ($0.00005 per run). No proxies, no browser. Set a **maximum cost per run** and the Actor stops cleanly at the limit.

### How to use it

- **Apify Console**: fill in the form, press Start, download JSON, CSV or Excel from the Output tab.
- **API**: `POST https://api.apify.com/v2/acts/lathewright~scholarly-search/run-sync-get-dataset-items?token=<token>` with the input JSON as the body.
- **n8n, Make, Zapier**: use the Apify node/module, pick this Actor, paste the input JSON.

### Use from an AI agent (MCP)

Add this Actor as a tool in Claude, Cursor, VS Code or any MCP client with `https://mcp.apify.com/?tools=lathewright/scholarly-search`. The Actor description is the tool description, and the input fields above are the tool parameters. Example prompts: "Find the most cited 2025 papers on retrieval-augmented generation with open-access PDFs", "Get metadata for these 30 DOIs".

### Data sources, robots.txt and fair use

Checked on 19 October 2026 for the exact paths the Actor requests:

- **OpenAlex API** (`api.openalex.org/works`): robots.txt allows the path. OpenAlex data are CC0. Since 2025 OpenAlex meters requests: without a key, all callers behind one IP address share a small free daily budget (about 100 requests), which can run out on shared infrastructure, so for anything beyond a quick query add your free `openalexApiKey` (openalex.org/settings/api) with its own daily budget. The Actor sends `mailto` and at most five requests per second (OpenAlex allows ten).
- **Crossref REST API** (`api.crossref.org/works`): no robots.txt is served; Crossref's API terms allow public use and ask clients to identify themselves (the Actor sends `mailto` in the query and in its User-Agent to join the polite pool) and to stay around one request per second, which the Actor does. Crossref returns HTTP 429 when a network sends too much traffic; the Actor then stops that source with a warning and keeps the OpenAlex results. During local testing from a shared network Crossref answered the first requests and rate-limited the rest, so its live behaviour on the platform should be checked after publishing.
- **PubMed E-utilities and the arXiv API are deliberately not used**: their robots.txt files disallow the API paths for generic crawlers. OpenAlex indexes both corpora, and PubMed ids are returned in `pmid` where known.
- Author names and affiliations are the published bibliographic record of each work; no contact details, ORCID profiles or emails are collected.

### FAQ

**Why do some abstracts come back empty?** Publishers do not always deposit abstracts; OpenAlex reconstructs them from an inverted index when available and Crossref returns them only for a minority of records.

**Why are counts different between sources?** OpenAlex counts citations across its whole corpus (including preprints and repositories); Crossref counts only DOI-to-DOI references registered by publishers.

**Can I filter by author or institution?** Put the name in `query` for a relevance match; structured author and institution filters are a planned addition.

# Actor input Schema

## `mode` (type: `string`):

`search` finds works by query. `doiLookup` fetches the works in `dois`.

## `query` (type: `string`):

Words or phrases searched in titles, abstracts and full text (OpenAlex) or bibliographic metadata (Crossref). Quotes for exact phrases.

## `sources` (type: `array`):

OpenAlex (richer metadata, topics, open-access links) and/or Crossref (publisher-registered DOI metadata).

## `fromYear` (type: `integer`):

Earliest publication year.

## `toYear` (type: `integer`):

Latest publication year.

## `workTypes` (type: `array`):

`article`, `preprint`, `review`, `chapter`, `book`, `conference`, `dataset`, `dissertation`, `report`. Empty = all.

## `openAccessOnly` (type: `boolean`):

Only works with a free full-text copy (OpenAlex) or an open licence (Crossref).

## `sortBy` (type: `string`):

Order of results from each source.

## `includeAbstract` (type: `boolean`):

Add the abstract text when the source has it.

## `maxResultsPerSource` (type: `integer`):

Cap per source; duplicates across sources (same DOI) are returned and billed once.

## `dois` (type: `array`):

DOIs with or without the https://doi.org/ prefix.

## `openalexApiKey` (type: `string`):

Free key from openalex.org/settings/api. Without it, requests share a small daily budget with every other user of the same IP address, so large runs need a key.

## `contactEmail` (type: `string`):

Sent as `mailto` to OpenAlex and Crossref so your traffic gets their faster, more reliable polite pool.

## `compactOutput` (type: `boolean`):

Return only the key fields (smaller, cheaper for AI agents to read).

## Actor input object example

```json
{
  "mode": "search",
  "query": "large language models evaluation",
  "sources": [
    "openalex",
    "crossref"
  ],
  "openAccessOnly": false,
  "includeAbstract": false,
  "maxResultsPerSource": 15,
  "compactOutput": false
}
```

# Actor output Schema

## `results` (type: `string`):

One JSON object per scholarly work (or per failed DOI lookup).

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "query": "large language models evaluation",
    "sources": [
        "openalex",
        "crossref"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("lathewright/scholarly-search").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "query": "large language models evaluation",
    "sources": [
        "openalex",
        "crossref",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("lathewright/scholarly-search").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "query": "large language models evaluation",
  "sources": [
    "openalex",
    "crossref"
  ]
}' |
apify call lathewright/scholarly-search --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lathewright/scholarly-search"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/F07NjUlkCu8wVpDrT/builds/0gCgOnSh7ZIvps9UG/openapi.json
