# Zenodo Research Search Scraper (`searchapi/zenodo-research-scraper`) Actor

Search the public Zenodo records API and extract publication metadata, creators, files, identifiers, licenses, communities, and download statistics.

- **URL**: https://apify.com/searchapi/zenodo-research-scraper.md
- **Developed by:** [Search API](https://apify.com/searchapi) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.99 / 1,000 search results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## Zenodo Research Search Scraper

Search Zenodo’s public research repository by keywords and filters, then save normalized publication, dataset, software, image, video, poster, presentation, lesson, or other research records to an Apify dataset.

The Actor uses Zenodo’s public records API. It does not require a Zenodo account, download deposited files, access private records, solve CAPTCHAs, or bypass access controls.

### What it extracts

Each record can include:

- Zenodo record and concept identifiers, DOI, canonical record URL, API URL, preview URL, and version URLs
- title, plain-text description, publication/creation/update dates, resource type, access right, embargo information, language, and version
- normalized creators and contributors, affiliations, ORCID/GND identifiers, keywords, subjects, references, and notes
- license, related identifiers, journal/conference/imprint/thesis metadata, grants, and communities
- normalized file metadata (name, byte size, checksum, public API/download URLs) without downloading the files
- views/download statistics, result page, total search result count, query, sort order, and collection timestamp

Raw API responses are not stored. Empty values are recursively removed, records are deduplicated by Zenodo record ID, HTML descriptions are converted to plain text, and only HTTP(S) URLs are emitted.

### Input

The Actor opens the public Zenodo search API using the values you would enter or select in Zenodo’s search interface.

| Field | Purpose | Default |
| --- | --- | --- |
| `query` | Keywords or a Zenodo advanced-search expression | empty |
| `resourceType` | Publication, dataset, software, poster, presentation, image, video, lesson, or other | `publication` |
| `accessRight` | Open, closed, embargoed, or restricted | all |
| `community` | Exact Zenodo community identifier | all |
| `startDate`, `endDate` | Inclusive publication date range (`YYYY-MM-DD`) | unbounded |
| `sortBy` | `mostrecent` or `bestmatch` | `mostrecent` |
| `maxItems` | Maximum unique records | `20` |
| `maxPages` | Pagination safety limit | `10` |
| `pageSize` | Stable records-per-page request size; writes are separately capped by `maxItems` | `25` |
| `maxRequestRetries` | Temporary-failure retries | `2` |
| `requestTimeoutSecs` | Timeout per API request | `30` |
| `requestDelayMillis` | Polite delay between pages | `500` |
| `useApifyProxy` | Use Apify Proxy | `false` |
| `proxyGroups`, `proxyCountryCode`, `proxyUrls` | Optional proxy configuration | unset |

The deprecated `limit` field remains accepted for backward compatibility, but cannot be combined with `maxItems`.

#### Example

```json
{
  "query": "machine learning",
  "resourceType": "dataset",
  "accessRight": "open",
  "startDate": "2024-01-01",
  "sortBy": "bestmatch",
  "maxItems": 50,
  "maxPages": 5
}
```

No-results searches finish successfully with an empty dataset. Invalid inputs fail before any request is sent.

### Run locally

Install dependencies and run through the Apify CLI:

```bash
npm ci
apify run --purge --input '{"query":"open science","maxItems":10}'
npm run validate:local
```

Run unit tests and schema validation with:

```bash
npm test
apify validate-schema
```

### Run on Apify Cloud

Deploy with `apify push`, then call the mapped Actor with a bounded JSON input. Results are written to the run’s default dataset. Public Store visibility, pricing, and monetization are separate settings and are not changed by deploying source code.

### Reliability and limitations

The Actor validates HTTP status and JSON content type before parsing, rejects malformed payloads, retries only temporary network/rate-limit/server errors with bounded exponential backoff, and supports direct, Apify Proxy, or custom proxy connections. Requests are sequential and rate-limited.

Results depend on Zenodo indexing, public API availability, search syntax, and rate limits. Optional metadata legitimately varies by deposit. File links and metadata are returned, but file contents are not downloaded.

# Actor input Schema

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

Keywords or Zenodo advanced-search expression, for example: machine learning or title:"open science".

## `resourceType` (type: `string`):

Restrict results to one Zenodo resource type. Publications are used by default.

## `accessRight` (type: `string`):

Optionally restrict records by public access status.

## `community` (type: `string`):

Optional Zenodo community slug, such as biodiversity-literature-repository.

## `startDate` (type: `string`):

Inclusive publication-date lower bound in YYYY-MM-DD format.

## `endDate` (type: `string`):

Inclusive publication-date upper bound in YYYY-MM-DD format.

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

Sort by newest records or Zenodo relevance.

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

Maximum unique dataset records to save across all pages.

## `maxPages` (type: `integer`):

Safety limit for Zenodo API pages.

## `pageSize` (type: `integer`):

Stable page size requested from Zenodo. Dataset writes are sliced separately to respect maxItems exactly.

## `maxRequestRetries` (type: `integer`):

Retries for temporary network, rate-limit, timeout, and server failures.

## `requestTimeoutSecs` (type: `integer`):

Maximum time allowed for each Zenodo API request.

## `requestDelayMillis` (type: `integer`):

Polite delay between successful API page requests.

## `useApifyProxy` (type: `boolean`):

Route requests through Apify Proxy. Direct public API access is the default.

## `proxyGroups` (type: `array`):

Optional Apify Proxy group names.

## `proxyCountryCode` (type: `string`):

Optional two-letter uppercase country code, for example US.

## `proxyUrls` (type: `array`):

Optional custom HTTP(S) proxy URLs. Do not use together with Apify Proxy.

## Actor input object example

```json
{
  "resourceType": "publication",
  "sortBy": "mostrecent",
  "maxItems": 20,
  "maxPages": 10,
  "pageSize": 25,
  "maxRequestRetries": 2,
  "requestTimeoutSecs": 30,
  "requestDelayMillis": 500,
  "useApifyProxy": false
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

## `keyValueStore` (type: `string`):

No description

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("searchapi/zenodo-research-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("searchapi/zenodo-research-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 '{}' |
apify call searchapi/zenodo-research-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,searchapi/zenodo-research-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/9TssgD7ZzRva5YLTp/builds/0mIBknaXMGEufGewS/openapi.json
