# Google Scholar Search Scraper: hits, citations, PDFs, CSV (`tallyrake/google-scholar-search-scraper`) Actor

Google Scholar search hits as flat CSV/JSON rows at $1.00 per 1,000 rows: title, link, authors, source, year, snippet, cited-by count and link, PDF link, per query with year filters. Search hits only, not author profiles or citation exports.

- **URL**: https://apify.com/tallyrake/google-scholar-search-scraper.md
- **Developed by:** [Tallyrake Data](https://apify.com/tallyrake) (community)
- **Categories:** Developer tools, SEO tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.25 / 1,000 results

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Google Scholar Search Scraper: hits, cited-by, PDFs, CSV

Search hits only. Not author profiles, co-author graphs, or citation-format exports. Google Scholar search hits as flat CSV/JSON rows. Give it queries, get each result's title, link, authors, source, year, snippet, cited-by count and link, PDF link when Scholar shows one, and Scholar's total-results estimate, with year filters. One row per hit with a stable `id`. $0.25 per 1,000 dataset rows.

### What you get

| Field | Example |
|---|---|
| `id` | stable per query and Scholar result id; the same paper keeps its `id` across runs even if its rank moves |
| `resultId` | Scholar's own id for the hit (`ZNoXfR7GejYJ`) |
| `query` | `google trends forecasting` |
| `position` | `1` (rank across pages, 10 per page) |
| `title` | `Predicting the present with Google Trends` |
| `url` | the result's link |
| `authors` | `H Choi, H Varian` |
| `source` | `Economic record - Wiley Online Library` |
| `year` | `2012` |
| `snippet` | Scholar's snippet |
| `citedBy`, `citedByUrl` | `4488`, link to the citing papers |
| `pdfUrl` | the \[PDF] link when Scholar shows one, else null |
| `kind` | `PDF`, `HTML`, `BOOK`, `CITATION` when Scholar tags the hit, else null |
| `versionCount` | `39` (from "All 39 versions"), else null |
| `totalResultsEstimate` | `119000` (Scholar's "About N results") |
| `fetchedAt` | ISO timestamp |

### Recipes

**Literature list for a topic.** Queries: your topic phrasings. `maxResultsPerQuery` 50. Year filters as needed. Sort the CSV by `citedBy`.

**Who cites what.** Take `citedByUrl` from a row and follow it in Scholar; this actor does not crawl citation graphs.

**Recent work only.** `yearFrom` 2024. Same queries, fresh papers first.

**Weekly watch.** Schedule the same queries weekly and diff the `id` column: a new `id` is a paper that was not in last week's hits; a rank move alone does not change it.

### Input

One query per line, exactly as you would type it into Scholar (quotes, `author:` and `source:` work). `maxResultsPerQuery` is 10 per page, up to 200. `pacingMs` (default 2,500 ms) is the jittered delay between page requests.

### Reliability and cost

Measured 2026-09-14 on Apify with datacenter proxy, one run: 8 queries, 2 pages each, `maxResultsPerQuery` 20: 16 requests, 160 rows, 0 of 16 blocked, 61 seconds, platform usage $0.0010. That run bills $0.04 in results (160 rows at $0.25 per 1,000). From this machine without a proxy the same day: 3 queries, 6 requests, 57 rows, 0 blocked, 18 seconds.

Scholar blocks by IP and cookie. Each session has its own cookie jar and proxy identity and is retired after 20 requests; a block (429, 403, or Scholar's "unusual traffic" page) rotates the session and retries with exponential backoff. That path was not exercised in the measured runs (0 blocked).

Pay per event: $0.25 per 1,000 dataset rows plus Apify platform usage. A query with no results produces no rows and no results charge.

### Where this sits on the shelf

Apify Store search for "google scholar", top 8 results on 2026-09-14, read from the Store API. Price is the pay-per-event charge per dataset item, converted to per 1,000 rows; users, runs and the failed-or-timed-out share are the Store's 30-day public stats for each listing.

| Listing | Users (30d) | Runs (30d) | Failed or timed out | Price per 1,000 rows |
|---|---|---|---|---|
| johnvc/google-scholar-api | 44 | 1,990 | 0% | $0.01 |
| scrape.badger/google-scholar-scraper | 22 | 2,231 | 2% | $0.01 |
| easyapi/google-scholar-scraper | 14 | 194 | 4% | $4.99 |
| crawlerbros/google-scholar-scraper | 5 | 135 | 1% | free |
| fetch\_cat/google-scholar-profiles-scraper | 3 | 4,534 | 4% | $5.00 |
| automation-lab/google-scholar-scraper | 3 | 88 | 2% | $10.00 |
| solidcode/google-scholar-scraper | 3 | 232 | 5% | free |
| nexgendata/google-scholar-scraper | 1 | 31 | 0% | $40.00 |
| tallyrake/google-scholar-search-scraper (this actor) | 0 | 0 | no public runs yet | $0.25 |

### Cost limit

If a run reaches the "Maximum total charge per run" you set, it stops in process rather than being aborted by the platform: the run ends with status SUCCEEDED, and the run status message on the run detail says how many rows were written and how many were found but not written and not billed. Re-running the same input writes and bills the same prefix again, so raise the cap before re-running if you want the rest.

### Limits

Search hits only. Not author profiles, co-author graphs, or citation-format exports. Scholar's "About N results" is an estimate. Google may change the page markup; the parser reads the `gs_` class names Scholar has used for years and fails loudly, not silently, if they change.

# Actor input Schema

## `queries` (type: `array`):

One Google Scholar query per line, exactly as you would type it (quotes and operators like author: work).

## `maxResultsPerQuery` (type: `integer`):

Results come in pages of 10; 20 means two pages per query. Up to 200.

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

Only results published in or after this year (Scholar's as\_ylo). Empty for no lower bound.

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

Only results published in or before this year (Scholar's as\_yhi). Empty for no upper bound.

## `language` (type: `string`):

Scholar interface language, e.g. en, de, es, fr, pt, ja, zh-CN.

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

Google Scholar blocks by IP quickly. Apify Proxy is recommended; the run rotates its session and backs off when it is blocked.

## `pacingMs` (type: `integer`):

Base jittered delay between page requests; 0 disables pacing.

## Actor input object example

```json
{
  "queries": [
    "google trends forecasting"
  ],
  "maxResultsPerQuery": 20,
  "language": "en",
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "pacingMs": 2500
}
```

# Actor output Schema

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

All result rows.

## `csv` (type: `string`):

The same rows as CSV.

# 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 = {
    "queries": [
        "google trends forecasting"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("tallyrake/google-scholar-search-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 = { "queries": ["google trends forecasting"] }

# Run the Actor and wait for it to finish
run = client.actor("tallyrake/google-scholar-search-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 '{
  "queries": [
    "google trends forecasting"
  ]
}' |
apify call tallyrake/google-scholar-search-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tallyrake/google-scholar-search-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/oehK1ZBiNyVaM0W7m/builds/2bKuXGHLRakUZWdQ3/openapi.json
