# Crossref Scraper (`dami_studio/crossref-scraper`) Actor

Crossref scraper and DOI lookup for 150M+ works: papers, preprints, book chapters and datasets, by keyword or journal ISSN. Each row holds the DOI, title, authors, journal, publisher, type, date and citation count, plus subjects, ISSN and abstract when deposited. $1.00 per 1,000 works.

- **URL**: https://apify.com/dami_studio/crossref-scraper.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** Developer tools, AI, Other
- **Features:** Limited permissions
- **Stats:** 4 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.97 / 1,000 works

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

**Crossref scraper for a research phrase or a journal ISSN, the works Crossref has a DOI for**: journal
articles, preprints, book chapters, datasets and dissertations, one row each, with the DOI, title,
authors, journal, publisher, publication date and citation count.

The honest part first. Crossref holds what publishers deposited with it, and plenty of them deposit
the bare minimum. Abstracts, subject terms and ISSNs are missing on a lot of older records, and the
citation count reads `0` both when a work genuinely has none and when nobody has told Crossref.

| | |
|---|---|
| **Input** | Search keywords, journal ISSNs, or both |
| **Output** | One row per work: DOI, title, authors, journal, publisher, type, date, citations, subjects, ISSN, abstract, link |
| **Ceiling** | 20,000 works per run, 10,000 when sorted newest first |
| **Account needed** | None, and no API key |
| **Price** | $1.00 per 1,000 works on the Free plan, a little less on paid plans. The free plan's $5 a month covers about 5,000 |

### 🔍 What Crossref Scraper does

It runs your keywords against Crossref's search, which reads across titles, authors, abstracts and
the rest of the deposited metadata, then pages through the matches so a large request keeps going
past the first hundred.

You can narrow it to one work type or to particular journals by ISSN, set a published-on-or-after
floor, and choose relevance, citation count or newest first as the order. Works with no DOI are
skipped, and a DOI that turns up twice is delivered once.

Nothing is written to your dataset until the whole set has been collected, so you get either the
full result set you asked for or a diagnostic row explaining why not. The one exception is a run
that gets close to its time limit: it writes the works it has, and a `TIME_LIMIT` row says so.

### 📋 What data you get from each Crossref work

| What you get | Field |
|---|---|
| The DOI, always present | `doi` |
| Title and authors | `title`, `authors` |
| The journal or book it appeared in, and its publisher | `journal`, `publisher` |
| What kind of work it is | `type` |
| When it was published, as precisely as the publisher said | `publishedDate` |
| How many works cite it, by Crossref's count | `citations` |
| Subject terms and the journal's ISSNs | `subjects`, `issn` |
| The abstract as plain text, when one was deposited | `abstract` |
| A link that resolves to the work | `url` |

### ▶️ How to scrape Crossref

1. Open [Crossref Scraper](https://apify.com/dami_studio/crossref-scraper) and click **Try for free**.
2. Type your keywords into **Search query**, or put an ISSN into **Journal ISSN**.
3. Set **Max works**. Start around 50 to see the row shape.
4. Pick a **Work type filter** and a **Sort order** if the defaults do not suit you, then click
   **Start**.
5. Download the dataset as JSON, CSV or Excel, or read it from the Apify API.

### 💰 How much does it cost to scrape Crossref?

**$1.00 per 1,000 works** on the Free plan. Paid plans pay a little less: $0.99 on Starter, $0.98 on Scale and $0.97 on Business. On the free plan, the $5 Apify
gives you each month covers about 5,000 works.

You pay per work delivered. Duplicate DOIs and works without a DOI are dropped before they are
counted, diagnostic rows are not charged, and a search that matches nothing is not charged. Set a
maximum cost on the run and it stops when it gets there.

### 📥 What you give it

```json
{
  "query": "CRISPR gene editing",
  "filterType": "journal-article",
  "fromDate": "2020-01-01",
  "sort": "is-referenced-by-count",
  "maxItems": 500
}
```

| Field | Default | What it is |
|---|---|---|
| `query` | none, the form starts with `deep learning` | The keywords to search for. Required unless you give an `issn`. |
| `filterType` | all types | One Crossref type: `journal-article`, `proceedings-article`, `book-chapter`, `book`, `posted-content` for preprints, `dataset`, `report`, `dissertation` or `monograph`. |
| `issn` | none | Journal ISSNs, such as `2169-3536`, up to 50. You get works from any of them. With an ISSN set, `query` can be empty and you get the journal's whole list. |
| `fromDate` | none | `YYYY-MM-DD`. Only works published on or after this date. There is no matching end date. |
| `sort` | `relevance` | `relevance`, `is-referenced-by-count` for most cited, or `published` for newest first, which stops at 10,000 works. |
| `maxItems` | `100` | How many works to return, up to 20,000. |
| `notionConnector` | none | Optional. Writes each work into your Notion once the run finishes. |
| `notionParentId` | none | Optional. The Notion data source to write into. |
| `proxyConfiguration` | off | Optional network settings. Off by default, and a normal run does not need it. |

`fromDate` has to be a real date shaped `YYYY-MM-DD`, and an ISSN has to be 8 characters like
`0950-382X`. Anything else stops the run with a `BAD_INPUT` row before a single search is made.

### 📤 What you get back

A real row from a run on 2 October 2026, with the author list cut short (the row carries all six
names):

```json
{
  "ok": true,
  "doi": "10.1067/mva.1993.50616",
  "title": "Light reflection rheography: A simple noninvasive screening test for deep vein thrombosis",
  "authors": ["Thomas W. Wakefield", "Subodh W. Arora", "David J. K. Lam", "..."],
  "journal": "Journal of Vascular Surgery",
  "publisher": "Elsevier BV",
  "type": "journal-article",
  "publishedDate": "1993-11",
  "citations": 0,
  "subjects": [],
  "issn": ["0741-5214"],
  "abstract": null,
  "url": "https://doi.org/10.1067/mva.1993.50616"
}
```

| Field | How to read it |
|---|---|
| `doi` | Always present. Works without one are dropped before they reach you, so it is safe as a key. |
| `authors` | Names as `Given Family`. An organisation shows up under its own name when there is no person. |
| `publishedDate` | `YYYY-MM-DD` where the publisher deposited a full date, otherwise `YYYY-MM` or just `YYYY`. Older records are usually the short forms. |
| `citations` | Crossref's referenced-by count, and `0` when Crossref has no figure at all. |
| `subjects`, `issn` | Arrays, often empty. Both depend on what the publisher deposited. |
| `abstract` | Plain text with the publisher's markup stripped out, or `null`. Missing far more often than present. |
| `url` | Crossref's own link, falling back to `https://doi.org/<DOI>`. |

### 🧾 Reading the output

Two kinds of row land in your dataset, and `ok` tells them apart.

| Row | How to spot it | Billed |
|---|---|---|
| A work | `ok: true` and a `doi` | yes |
| A diagnostic | `ok: false` and an `errorCode` | no |

The overview table in the Apify Console shows the work columns only, so a diagnostic row looks blank
there. Switch to the JSON or All fields view to read it.

| Code | What it means |
|---|---|
| `BAD_INPUT` | No query and no ISSN, a `fromDate` that is not a real `YYYY-MM-DD` date, an ISSN that is not one, or a search Crossref itself refused. The row says which. |
| `NO_RESULTS` | The search worked and nothing matched. `totalResults` on the row shows what Crossref counted. |
| `RATE_LIMITED` | Crossref asked for a slower pace than the run could keep. |
| `SERVER_ERROR` | Crossref answered with a server error. Usually passes. |
| `NOT_SERVED` | This request was not served this run. Re-run it later. Runs before 13 October 2026 wrote `BLOCKED` here, and runs from 13 to 17 October wrote `NETWORK`. |
| `NETWORK` | Crossref was unreachable. Re-run it. |
| `TIME_LIMIT` | The run got close to its time limit and stopped on its own. The works delivered before that are complete and charged. Give the run more time, or ask for fewer works, to get the rest. |

A run that ends on one of these rows still finishes as succeeded, including when the time limit
stopped it before any work came back: the `TIME_LIMIT` row and an amber status message say so.

### 💡 What people use it for

- Building a DOI list for a literature review, then fetching the papers themselves elsewhere.
- Sorting a field by citation count to see which work everything else is built on.
- Listing what one journal published since a date, with its ISSN in `issn` and the date in
  `fromDate`.
- Checking which publisher holds a set of papers before writing to them about access.

### 🚧 What it does not do

- **No lookup by DOI or by author.** Keywords and journal ISSNs are the ways in.
- **No end date.** `fromDate` sets a floor and nothing sets a ceiling.
- **Newest first stops at 10,000 works**, and a few records carry publication dates years ahead,
  which sort to the top. In one test the first rows were dated 2115 and 2106. Deep in that order,
  works sharing a date can repeat across pages; repeats are dropped and not charged, so a full run
  ends a little short (9,872 of 10,000 in that test).
- **Abstracts are mostly missing.** Crossref only has one if the publisher deposited it.
- **`citations` cannot tell you zero from unknown.** Both read `0`.
- **No full text, and no PDF.** You get the DOI and the link, not the paper.
- **Paging stops on a short page.** If Crossref returns fewer than 100 items in one page, the run
  treats that as the end even when its own total says otherwise.
- **All or nothing.** A failure partway through discards what had been collected, so you get a
  diagnostic row rather than a partial set.
- **Crossref is publisher-deposited metadata**, not a curated index. Quality varies by publisher and
  by decade.
- It is not an official Crossref tool. Dami's Studio is independent and is not affiliated with or endorsed by Crossref, or by any other company named on this page.

### 🧭 Which research scraper do you need?

| If you want | Use |
|---|---|
| arXiv preprints with full abstracts and PDF links | [arXiv Scraper](https://apify.com/dami_studio/arxiv-scraper) |
| Anything with a registered DOI, with its journal, publisher and ISSN | This one |
| Papers with readable abstracts, institutions and open-access links | [OpenAlex Scraper](https://apify.com/dami_studio/openalex-scraper) |
| Patents rather than papers | [Google Patents Search Scraper](https://apify.com/dami_studio/google-patents-search-scraper) |
| Book records by keyword, title or ISBN | [Books Scraper](https://apify.com/dami_studio/books-scraper) |
| Encyclopedia articles as plain text | [Wikipedia Scraper](https://apify.com/dami_studio/wikipedia-scraper) |
| arXiv, OpenAlex and Wikipedia searches as tools for an AI agent | [Research MCP Server](https://apify.com/dami_studio/research-mcp-server) |

### ❓ Questions people ask

#### Do I need a Crossref account or an API key?

No. Crossref publishes this metadata openly and the actor reads it directly.

#### Why are so many abstracts null?

Crossref stores what the publisher sent. Most publishers never deposit an abstract, so the field is
empty far more often than it is filled.

#### Can I look a paper up by its DOI?

Not here. This searches by keyword and by journal ISSN.

#### Can I list everything one journal published?

Yes. Put its ISSN in `issn` and leave the query empty. A big journal holds more than one run
delivers, so sort newest first or by citations to get the end you care about.

#### Why did I get fewer works than I asked for?

Either Crossref has fewer matches, or a page came back short and paging stopped there. You are
charged for what arrived.

#### Can I call it from code or connect it to an AI assistant?

The [API tab](https://apify.com/dami_studio/crossref-scraper/api/python) has code for Python, JavaScript and the CLI.
MCP clients like Claude and ChatGPT use
`https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/crossref-scraper`; coding assistants can load [our skill
file](https://api.apify.com/v2/key-value-stores/BTBHU3DdiuoF4JOsK/records/apify-open-data-research-SKILL.md). All
three bill your Apify account at the same price.

#### Is scraping Crossref legal?

Crossref publishes this metadata openly. Apify's write-up on
[the legality of web scraping](https://blog.apify.com/is-web-scraping-legal/) is a good starting
point, and we are not lawyers.

### 🆘 If something breaks

Open the **Issues** tab on the actor page. Send the run ID and the query you used. The `errorCode` on
the diagnostic row usually names the problem on its own.

# Actor input Schema

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

Keywords to search Crossref for across titles, authors, abstracts, and metadata (e.g. "deep learning", "CRISPR gene editing", "climate change adaptation"). It can be left empty only when you give a journal ISSN below.

## `fromDate` (type: `string`):

Only return works published on or after this date, in YYYY-MM-DD format (e.g. 2020-01-01). Leave empty for no date floor.

## `filterType` (type: `string`):

Only return works of this Crossref type. Leave empty for all types. "journal-article" is the most common for research papers.

## `issn` (type: `array`):

Only works from these journals, by ISSN, such as 2169-3536. Give several and you get works from any of them. With an ISSN set you can leave the search query empty and get the journal's whole list.

## `sort` (type: `string`):

How to order results. "Relevance" matches the query best; "Most cited" surfaces influential papers; "Newest first" sorts by publication date descending and stops at 10,000 works.

## `maxItems` (type: `integer`):

Maximum number of scholarly works to return. Uses deep cursor pagination to fetch beyond 100 reliably.

## `notionConnector` (type: `string`):

Optional. Write each result as a page into your Notion when the run finishes. Authorize a Notion connector once in Settings → API & Integrations → MCP connectors, then pick it here. Leave empty to skip (default), results are always saved to the dataset regardless.

## `notionParentId` (type: `string`):

Optional. The Notion data source ID of the database to write into (only used if a Notion connector is set). Leave empty to create the pages privately in your workspace instead.

## `proxyConfiguration` (type: `object`):

Optional, and not needed for a normal run.

## Actor input object example

```json
{
  "query": "deep learning",
  "fromDate": "",
  "filterType": "",
  "sort": "relevance",
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Scraped rows are stored in the default dataset (one row per result). Empty or failed runs return a single uncharged diagnostic row instead.

# 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": "deep learning"
};

// Run the Actor and wait for it to finish
const run = await client.actor("dami_studio/crossref-scraper").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": "deep learning" }

# Run the Actor and wait for it to finish
run = client.actor("dami_studio/crossref-scraper").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": "deep learning"
}' |
apify call dami_studio/crossref-scraper --silent --output-dataset

```

## MCP server setup

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

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/vrPcFIdyyvywJyGDt/builds/EZ67eshG8CJI4dzns/openapi.json
