# Research Paper Search: OpenAlex, arXiv, PubMed, Crossref (`trim_invitation_set/research-paper-search`) Actor

One query searches OpenAlex, arXiv, PubMed and Crossref at once. Duplicates are merged into one record per paper with abstract, DOI, citation count and open-access PDF link, ranked across all four. A full run takes about 7-10 seconds; no API keys. AI agents can call it via the Apify MCP server.

- **URL**: https://apify.com/trim_invitation_set/research-paper-search.md
- **Developed by:** [Danielle Lesin](https://apify.com/trim_invitation_set) (community)
- **Categories:** AI, Agents, Education
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 paper returneds

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

## Research Paper Search: OpenAlex, arXiv, PubMed and Crossref in one query

Search four major scholarly databases with a single query and get back **one clean, deduplicated list of papers**: titles, authors, year, venue, DOI, abstract, citation count and links to free PDFs or full text where they exist.

- **4 databases, 1 call:** OpenAlex (all fields, citation counts), arXiv (preprints), PubMed (biomedicine) and Crossref (DOIs for almost every journal) are searched in parallel.
- **Duplicates merged:** a paper found in several databases appears once. Each copy fills in what the others are missing (abstract, PDF link, citation count, DOI).
- **Ranked across databases:** reciprocal rank fusion puts papers that rank high in several databases first. Sorting by newest or most cited is applied after merging, so results stay on topic.
- **Fast and resilient:** the four database searches finish in about 2-3 seconds, and a whole run, including start-up, takes about 7-10 seconds. If one database fails, the others still answer, and the run summary tells you which one failed.
- **No API keys required.** You can optionally add your own free OpenAlex key.
- **Built for AI agents too:** works through the Apify API and the Apify MCP server, so an agent can call it as a single literature-search tool.

### Why one call beats four separate searches

Searching arXiv, PubMed, OpenAlex and Crossref separately means four queries, four result formats and a lot of duplicates: the same paper shows up as an arXiv preprint, a PubMed record and a Crossref DOI. Then you still have to work out which results matter most.

This tool does that work for you. It returns one schema for every paper, one record per paper, and one ranking that rewards papers several databases agree on. For an AI agent, that means one tool call and fewer tokens spent on duplicates.

### Use cases

- Literature reviews and related-work sections
- Finding open-access PDFs for a topic (`openAccessOnly: true`)
- Biomedical evidence searches (PubMed together with journal and preprint coverage)
- Keeping up with recent preprints and papers in a field (`sortBy` newest, `yearFrom`)
- Finding the most cited papers on a topic
- Giving AI research assistants and RAG pipelines grounded sources with DOIs and abstracts

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `query` | string (required) | | What to search for, in plain words, e.g. "CRISPR off-target effects" |
| `sources` | array | all four | Any of `openalex`, `arxiv`, `pubmed`, `crossref` |
| `maxResults` | integer | 25 | Papers returned after duplicates are merged. You pay per paper returned. |
| `sortBy` | string | `relevance` | Relevance puts papers ranked high in several databases first. Newest or most-cited sorting is applied after merging. |
| `yearFrom` | integer | | Only papers published in or after this year |
| `yearTo` | integer | | Only papers published in or before this year |
| `openAccessOnly` | boolean | false | Only return papers that are free to read |
| `includeAbstracts` | boolean | true | Turn off for shorter results (titles and links only) |
| `openAlexApiKey` | string | | Optional free OpenAlex key, which gives you your own daily budget |
| `contactEmail` | string | | Passed to OpenAlex, NCBI and Crossref so your requests use their faster "polite" pools |

#### Input example

```json
{
  "query": "climate change coral reefs",
  "sources": ["openalex", "arxiv", "pubmed", "crossref"],
  "maxResults": 25,
  "sortBy": "relevance",
  "yearFrom": 2005,
  "openAccessOnly": false,
  "includeAbstracts": true
}
```

### Output

Each paper is one dataset item with these fields: `rank`, `title`, `authors`, `year`, `publicationDate`, `venue`, `type`, `doi`, `url`, `pdfUrl`, `fullTextUrl`, `isOpenAccess`, `citationCount`, `abstract`, `ids` (openalex, arxiv, pmid, pmcid), `sources` (which databases returned it) and `query`.

#### Output example (from a real test run; author list and abstract shortened here)

```json
{
  "rank": 1,
  "title": "Coral Reefs Under Rapid Climate Change and Ocean Acidification",
  "authors": ["Ove Hoegh-Guldberg", "Peter J. Mumby", "A. J. Hooten", "..."],
  "year": 2007,
  "publicationDate": "2007-12-13",
  "venue": "Science",
  "type": "review",
  "doi": "10.1126/science.1152509",
  "url": "https://doi.org/10.1126/science.1152509",
  "pdfUrl": "https://openresearch-repository.anu.edu.au/bitstreams/ab9744aa-7521-4de0-8d87-55d2919d2206/download",
  "fullTextUrl": "https://openresearch-repository.anu.edu.au/bitstreams/ab9744aa-7521-4de0-8d87-55d2919d2206/download",
  "isOpenAccess": true,
  "citationCount": 5886,
  "abstract": "Atmospheric carbon dioxide concentration is expected to exceed 500 parts per million ...",
  "ids": { "openalex": "W2123920115", "pmid": "18079392" },
  "sources": ["openalex"],
  "query": "climate change coral reefs"
}
```

Each run also saves a `SUMMARY` record in its key-value store: which databases answered, how many papers each found, and how long each took.

### Pricing

Pay per result: you are charged once for each paper returned (event `paper-result`). The current price per paper is shown on this page. Duplicates are merged **before** counting, so you never pay twice for the same paper. Use `maxResults` to control how many papers you get. The run stops cleanly when it reaches your maximum cost per run.

### FAQ

**Do I need API keys?**
No. Optionally, add a free OpenAlex key (from openalex.org) to get your own daily OpenAlex budget.

**What happens if a database is down or rate-limited?**
The other databases still answer, and the run's `SUMMARY` record shows which one failed. Without a key, OpenAlex may sometimes refuse requests when its shared free budget runs out.

**How are duplicates detected and merged?**
The same paper found in several databases becomes one record, and each copy fills in fields the others lack, such as abstract, PDF link, citation count and DOI. The `sources` field shows which databases found it.

**Does it download full-text PDFs?**
No. It returns links (`pdfUrl`, `fullTextUrl`) to free versions when the databases know of one.

**Can I search only one database?**
Yes. Set `sources`, e.g. `["pubmed"]` for biomedicine only or `["arxiv"]` for preprints only.

**Can AI agents use it?**
Yes. Call it through the Apify API or add it as a tool through the Apify MCP server. The input is a plain-language query, and the output is one consistent JSON schema per paper.

**How fast is it?**
The four database searches finish in about 2-3 seconds; a whole run, including start-up, takes about 7-10 seconds.

# Actor input Schema

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

What to search for, in plain words, for example "CRISPR off-target effects" or "transformer models for protein folding".

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

Which databases to search. All four by default: OpenAlex (all fields, citation counts), arXiv (preprints), PubMed (biomedicine) and Crossref (DOIs for almost every journal).

## `maxResults` (type: `integer`):

How many papers to return after duplicates across databases are merged. You pay per paper returned.

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

Relevance puts papers that rank high in several databases first.

## `yearFrom` (type: `integer`):

Only papers published in or after this year.

## `yearTo` (type: `integer`):

Only papers published in or before this year.

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

Only return papers that are free to read.

## `includeAbstracts` (type: `boolean`):

Turn off for shorter results when you only need titles and links.

## `openAlexApiKey` (type: `string`):

OpenAlex gives each key its own free daily budget. Without one, OpenAlex may sometimes refuse requests when its shared free budget runs out; the other databases still answer. Get a free key at openalex.org/settings/api.

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

Passed to OpenAlex, NCBI and Crossref so they route your requests to their faster "polite" pools.

## Actor input object example

```json
{
  "query": "CRISPR off-target effects",
  "sources": [
    "openalex",
    "arxiv",
    "pubmed",
    "crossref"
  ],
  "maxResults": 25,
  "sortBy": "relevance",
  "openAccessOnly": false,
  "includeAbstracts": true
}
```

# Actor output Schema

## `papers` (type: `string`):

The merged, ranked papers with metadata, abstracts and links.

## `summary` (type: `string`):

Which databases answered and how many papers each found.

# 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": "CRISPR off-target effects"
};

// Run the Actor and wait for it to finish
const run = await client.actor("trim_invitation_set/research-paper-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": "CRISPR off-target effects" }

# Run the Actor and wait for it to finish
run = client.actor("trim_invitation_set/research-paper-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": "CRISPR off-target effects"
}' |
apify call trim_invitation_set/research-paper-search --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,trim_invitation_set/research-paper-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/A9wBu0lLxcy6OWPpk/builds/tWDICfHgKS3QEa14P/openapi.json
