# Research Papers Citations Monitor - Google Scholar Alternative (`neverempty/research-papers-citations-monitor`) Actor

Search research papers and citations in OpenAlex, the open scholarly index (CC0): title, authors, affiliations, venue, DOI, cited-by count, open-access PDF link, abstract. Track who cites your papers, or monitor a search for new papers only. A Google Scholar alternative on official open data.

- **URL**: https://apify.com/neverempty/research-papers-citations-monitor.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** AI, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.40 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 Papers Citations Monitor - Google Scholar Alternative

**Source: [OpenAlex](https://openalex.org), the open index of scholarly works. OpenAlex data is released under CC0 (public domain).** This Actor reads the official OpenAlex API. It does not read Google Scholar, and it does not open publisher pages.

Search research papers, get their **cited-by counts**, see **which new papers cite a paper**, and **monitor** a search or a list of papers so that each run returns only what changed.

**No API key needed, with one limit.** Without a key OpenAlex gives each IP address a small daily budget, and Apify addresses are shared. If that shared budget is used up, the run returns a free row that says so and charges nothing. For steady scheduled use, put your own OpenAlex API key into `openAlexApiKey`: it is free and OpenAlex gives every key $1 of usage per day.

Three ways to use it:

| You give | You get |
|---|---|
| A search (text, author, institution, journal or conference, field, years, open access) | One row per paper: title, authors and affiliations, publication date, venue, DOI, cited-by count, open-access PDF link, abstract |
| A list of papers (DOI or OpenAlex ID) | One row per paper with its cited-by count, followed by the newest papers that cite it |
| Either of the above with **monitoring** on | Only new papers since the last run, or only the papers whose citation count rose, with their new citing papers |

### Why use this as a Google Scholar alternative

- **Official open data, no blocking.** OpenAlex publishes this data for reuse (CC0) and its robots.txt allows the API. No CAPTCHA, no proxy.
- **Exact authors.** Filter by ORCID or OpenAlex author ID, so namesakes are not mixed in. If you only have a name and several authors share it, the run returns the candidates for free instead of silently picking one.
- **Citation tracking that tells you what is new.** Give DOIs once, schedule the run, and get a row only when a citation count rises, together with the new citing papers.
- **You are told what happened.** A run that finds nothing, finds nothing new, cannot read the source or stops at a limit returns a row that says so. Those rows are not charged.

### Input

| Field | What it does |
|---|---|
| `search` | Words to look for in the title and abstract. Use double quotes for an exact phrase. |
| `searchScope` | `title-abstract` (used when left empty) or `fulltext`. Full text also matches papers that only mention the words in their body. |
| `authorIds` | ORCID iDs (`0000-0002-1825-0097`) or OpenAlex author IDs (`A5023888391`). One kind per run. |
| `authorName` | A plain name, when you have no ID. One match: used. Several matches: candidate rows (free), no paper is read. |
| `institutionIds` | ROR IDs (`00f54p054`) or OpenAlex institution IDs (`I97018004`). One kind per run. |
| `sourceIds` | Journals, conferences or repositories by ISSN (`0028-0836`) or OpenAlex source ID (`S137773608`). One kind per run. |
| `field` | One of the 26 OpenAlex fields (Computer Science, Medicine, ...). Matches the paper's primary topic. |
| `publicationYearFrom`, `publicationYearTo` | Publication year range. |
| `openAccess` | `any`, `open` or `closed`. |
| `sortBy` | `newest`, `most-cited` or `relevance` (relevance needs `search`). |
| `maxPapers` | How many papers a search returns at most (default 100, up to 10,000 per run). |
| `papers` | Citation tracking: DOIs (`10.1038/nature14539`) or OpenAlex work IDs (`W2919115771`), up to 1,000. Not combined with the search fields. |
| `maxCitingPapersPerPaper` | Newest citing papers returned per paper (default 20, 0 to 200). |
| `includeAbstract` | Rebuild the abstract text when OpenAlex holds one (default on). |
| `monitoringMode` | Return only what is new since the last run (see below). |
| `resetMonitoringState` | Forget what monitoring remembers for this search or these papers. |
| `openAlexApiKey` | Optional. Your own OpenAlex API key (see "Limits of the source"). |

Example: newest open-access papers on a topic from one institution

```json
{ "search": "\"retrieval augmented generation\"", "institutionIds": ["00f54p054"], "openAccess": "open", "maxPapers": 50 }
```

Example: citation tracking

```json
{ "papers": ["10.1038/nature14539", "W2741809807"], "maxCitingPapersPerPaper": 10 }
```

### Output

One row per paper. Main columns:

| Column | Meaning |
|---|---|
| `recordType` | `paper`, or `citing-paper` (a paper that cites the one in `citesPaperId`) |
| `title`, `type`, `language` | As recorded by OpenAlex |
| `authorNames`, `authors` | Author names; per author the OpenAlex author ID, institutions and countries |
| `authorCount`, `authorListTruncated` | OpenAlex list answers hold at most 100 authors per paper. When a paper has 100 or more, `authorListTruncated` is true, `authorCount` is null and the lists hold the first 100 |
| `publicationDate`, `publicationYear`, `publicationDateIsInFuture` | Publication date as recorded. OpenAlex holds some papers with a future date; the flag marks them |
| `venue`, `venueType`, `venueIssn`, `publisher` | Where it was published |
| `doi`, `doiUrl`, `openAlexId`, `openAlexUrl`, `landingPageUrl` | Identifiers and links |
| `citedByCount` | Number of works in OpenAlex that cite this paper |
| `isOpenAccess`, `openAccessStatus`, `openAccessPdfUrl`, `openAccessUrl` | Open-access state and the link to a free PDF when OpenAlex knows one (null otherwise) |
| `abstract`, `hasAbstract` | Abstract text rebuilt from OpenAlex's word index; null when OpenAlex has none |
| `topic`, `field` | Primary topic and its field |
| `isRetracted`, `referencedWorksCount` | Retraction flag; length of the reference list |
| `change`, `previousCitedByCount`, `citedByCountChange`, `previousCheckedAt` | Filled by monitoring |
| `searchedFor`, `searchScope` | The exact search and filter the run sent; where the text was looked for |
| `status`, `note` | `ok` for paper rows; anything else is a free row that explains what happened |

Values that OpenAlex does not hold are null. Nothing is estimated.

### Monitoring

**A search.** The first run remembers the matching papers published in the last 365 days and returns no paper (free). Later runs with the same search return only papers that were not there before, as `change: new-paper`. Papers are compared by OpenAlex ID, not by date, because OpenAlex often adds a paper days or weeks after its publication date. Limits: a paper added with a publication date older than 365 days is not seen, and a search matching more than 10,000 papers in that window is refused with a free row (narrow it).

**A list of papers.** The first run remembers each citation count and the list of citing papers (free). Later runs return a paper only when its citation count rose or a new citing paper appeared: one `paper` row with `previousCitedByCount` and `citedByCountChange`, then one `citing-paper` row for each new citing paper. Papers with more than 10,000 citing papers cannot be monitored (the plain lookup still works for them).

A monitoring run that compares and finds nothing new returns one free row and is charged one small `search-checked` event. If the maximum charge of a run stops it early, what was not delivered is not remembered and comes back in the next run. OpenAlex updates about once a day at most, so a daily or weekly schedule is enough. Do not run the same monitoring search twice at the same moment.

### Pricing

Pay per result: each paper row (`paper` and `citing-paper`) is one `paper-returned` event. Rows that explain an empty or failed run, author candidates and the first monitoring run are free. A monitoring run with nothing new costs one `search-checked` event.

### Limits of the source (measured 2026-10-06)

- **Daily budget without a key.** OpenAlex gives each IP address a daily budget of $0.10 at its own list prices: about 100 text-search requests or 1,000 filter-only requests per day (one request returns up to 200 papers). Apify IP addresses are shared, so the budget can already be used up. When that happens the run returns a free row saying so. A free OpenAlex API key in `openAlexApiKey` raises the budget to $1 per day according to OpenAlex. The run log shows the budget left.
- **Citation counts differ between indexes.** For six highly cited 2025 Nature papers, OpenAlex's count was 3% to 16% lower than Crossref's `is-referenced-by-count` for the same DOI. Google Scholar counts differently again. Compare counts over time within one index, not across indexes.
- `citedByCount` and the number of citing papers that can be listed can differ by a few (1,055 against 1,047 for one paper).
- **Author lists stop at 100** in list answers (see `authorListTruncated`).
- With `searchScope: fulltext` a matching paper may not show the words in its title or abstract (20 of 50 did in one test, against 50 of 50 with the title-and-abstract search). In the title-and-abstract search, commas and `|` in the text are read as spaces. OpenAlex does not share the abstract text of some papers: such a paper can still match on its abstract while `abstract` is null (11 of 50 in one test on a single journal).
- An author, institution or source ID that does not exist returns the free `no-results` row, the same as a real empty result.
- The same paper can exist twice in OpenAlex (for example a preprint and the published version) under different IDs.

### Related Actors

- [arXiv Scraper](https://apify.com/neverempty/arxiv-scraper) - preprints straight from arXiv
- [PubMed Scraper](https://apify.com/neverempty/pubmed-scraper) - biomedical literature from PubMed

### Is it legal to use this data?

OpenAlex states that its data is released under CC0 and its API robots.txt allows access. Author names and affiliations are part of the published scholarly record; this Actor does not collect emails, phone numbers or ORCID iDs in paper rows. You are responsible for how you use the output.

### Thanks for using this Actor

We build these tools for people who run them every day, and we improve them from what users tell us.

- **Missing a field, or need another filter?** Tell us in the **Issues** tab. If the data is there, we add it.
- **Found a bug or a wrong value?** Post the run ID in the **Issues** tab. Wrong data is the thing we fix first.

If this Actor saved you time, a short review helps other people find it.

# Actor input Schema

## `search` (type: `string`):

Words to look for in the title and abstract of papers (see Search in). Put a phrase in double quotes for an exact match. Commas and | are read as spaces. Leave empty to list papers by author, institution, source or field only.

## `searchScope` (type: `string`):

Where the search text is looked for. Left empty, the run searches title and abstract, so the returned papers show the words. Full text also matches papers that only mention the words somewhere in their body: more results, many of them off-topic.

## `authorIds` (type: `array`):

Papers by any of these authors. Use ORCID iDs (0000-0002-1825-0097) or OpenAlex author IDs (A5023888391), one kind per run. IDs are exact: namesakes are not mixed in.

## `authorName` (type: `string`):

A plain author name. If exactly one author in OpenAlex has this name, the run uses that author. If several do, the run returns the candidates (name, ID, institution, number of works) free of charge and reads no paper: pick one and put the ID into Authors.

## `institutionIds` (type: `array`):

Papers with at least one author affiliated with any of these institutions. Use ROR IDs (00f54p054 for Stanford University) or OpenAlex institution IDs (I97018004), one kind per run.

## `sourceIds` (type: `array`):

Papers published in any of these journals, conference proceedings or repositories. Use ISSNs (0028-0836 for Nature) or OpenAlex source IDs (S137773608), one kind per run.

## `field` (type: `string`):

Keep only papers whose primary topic is in this OpenAlex field.

## `publicationYearFrom` (type: `integer`):

Keep papers published in this year or later.

## `publicationYearTo` (type: `integer`):

Keep papers published in this year or earlier.

## `openAccess` (type: `string`):

Keep every paper, only open-access papers, or only papers that are not open access.

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

Order of a search. Relevance needs a search text. Monitoring ignores this.

## `maxPapers` (type: `integer`):

How many papers a search returns at most (up to 10,000 per run). Monitoring ignores this and returns every new paper.

## `papers` (type: `array`):

Citation tracking: give DOIs (10.1038/nature14539) or OpenAlex work IDs (W2919115771), up to 1,000. Each paper comes back as one row with its cited-by count, followed by the newest papers that cite it. Cannot be combined with the search fields above.

## `maxCitingPapersPerPaper` (type: `integer`):

For citation tracking without monitoring: how many of the newest citing papers to return for each paper (0 to 200). Each citing paper is one row. With monitoring on, every new citing paper is returned instead.

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

Rebuild the abstract text when OpenAlex holds one. Turn off for lighter rows.

## `monitoringMode` (type: `boolean`):

With a search: the first run remembers the matching papers published in the last 365 days and returns nothing; later runs with the same search return only papers that were not there before. With papers: the first run remembers each citation count and its citing papers; later runs return only the papers whose citation count rose, with their new citing papers. The first run is free.

## `resetMonitoringState` (type: `boolean`):

Forget what was remembered for this search (or these papers) and start again from a new first run.

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

Not needed for normal use. Without a key OpenAlex gives each IP address a small daily budget, shared with other users of the same address. If a run reports that the daily budget is used up, a free key from openalex.org raises it tenfold. The key is sent only to api.openalex.org.

## Actor input object example

```json
{
  "search": "retrieval augmented generation",
  "openAccess": "any",
  "sortBy": "newest",
  "maxPapers": 100,
  "maxCitingPapersPerPaper": 20,
  "includeAbstract": true,
  "monitoringMode": false,
  "resetMonitoringState": false
}
```

# Actor output Schema

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

One row per research paper from OpenAlex: title, authors and affiliations, publication date, venue, DOI, cited-by count, open-access PDF link and abstract. Citation tracking adds one row per citing paper. Runs that could not read OpenAlex, found nothing or nothing new, or hit a limit return a row that says so and is not charged.

# 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 = {
    "search": "retrieval augmented generation"
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/research-papers-citations-monitor").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 = { "search": "retrieval augmented generation" }

# Run the Actor and wait for it to finish
run = client.actor("neverempty/research-papers-citations-monitor").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 '{
  "search": "retrieval augmented generation"
}' |
apify call neverempty/research-papers-citations-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,neverempty/research-papers-citations-monitor"
        }
    }
}
```

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/yJFaTiQ8Il7OOd9kI/builds/zyXD82khWGbTasCqn/openapi.json
