---
title: "Google Scholar API: Search Papers and Citations as JSON"
description: "Search Google Scholar as JSON: the search endpoint's parameters, a recorded response with citation counts, and a flat 1 credit per call."
url: https://perceptlayer.com/blog/google-scholar-api
---

[Blog](https://perceptlayer.com/blog) / [API guides](https://perceptlayer.com/blog/category/api-guides)

# Google Scholar API: Search Papers and Citations as JSON

13 Sept 2026 Perceptlayer 7 min read

Google's Scholar pages don't point to a developer API, so a third-party one is the practical route. The Perceptlayer Google Scholar API gives you five `GET` endpoints that return JSON: search, author, author-citation, author-co-authors and cite. Each successful call costs 1 credit, and failed calls cost nothing. Send your key in the `X-API-Key` header and you can have a result list in one request. Only search has a recorded response, so the other four sections list parameters and leave the details to their endpoint pages.

## Key takeaways

-   `GET /v1/google-scholar/search` takes an optional `q` (up to 500 characters) plus `as_ylo`, `as_yhi`, `start`, `num`, `cites` and `cluster`.
-   Each organic result carries `title`, `result_id`, `link`, `snippet` and `publication_info.summary`. Cited results add `inline_links.cited_by.total`.
-   The `cites` parameter takes a string. In the recording, `cited_by.link` carries the same value as `cited_by.cites_id`.
-   All five endpoints cost 1 credit per successful call. The free tier's 1,000 monthly credits cover 1,000 calls.
-   The author endpoints take a required `user` parameter, `author-citation` also needs a `citation_id`, and `cite` requires `q`. Only search has a recorded response here; those four are covered by parameters alone.

## Is there an official Google Scholar API?

Google doesn't point to one on its Scholar pages. [Google's Scholar about page](https://scholar.google.com/intl/en/scholar/about.html) describes a search product and doesn't mention a developer API. That isn't proof that none exists, so check Google's own documentation before you rely on this. If you need paper search, author profiles or citation counts as structured data, you either build a parser yourself or call a service that returns the fields as JSON.

That second route is what this guide covers. The Perceptlayer endpoints return named fields, so a script can read `title` and `inline_links.cited_by.total` without touching HTML. Data is collected from publicly available sources and returned as found at the time of the call. You get no guarantee of completeness, so treat counts as a snapshot.

If you only need open metadata, other services fit better. [OpenAlex](https://docs.openalex.org/), [Crossref](https://www.crossref.org/documentation/retrieve-metadata/rest-api/) and [Semantic Scholar](https://www.semanticscholar.org/product/api) publish documented APIs for scholarly metadata. Use Scholar-specific endpoints when you need what Google Scholar shows: its ranking, its "cited by" counts and its author profiles.

## What does a Google Scholar search request look like?

One `GET` to `/v1/google-scholar/search` with a query returns a page of papers. This request asks for ten results for "machine learning", in English, published since 2020:

```bash
curl "https://api.perceptlayer.com/v1/google-scholar/search?q=machine+learning&hl=en&num=10&as_ylo=2020" \
  -H "X-API-Key: $API_KEY"
```

If you don't have a key yet, [get a free API key](https://perceptlayer.com/signup) first. The [authentication docs](https://docs.perceptlayer.com/authentication) cover the header and the `api_key` query-parameter fallback for clients that can't set headers. Keys start with `sk_live_`.

You can also run the call without writing code. The [Google Scholar API page](https://perceptlayer.com/apis/google-scholar) has a playground: pick the endpoint, fill in the parameters and run a real call with your key.

## Which parameters does the search endpoint take?

The search endpoint has no required parameters. Everything is optional, though a request without `q` or `cites` gives you little to look at. The table gives each parameter's type and allowed values, which is all the catalogue documents. Defaults and page sizes aren't specified.

| Parameter | Type | Notes |
| --- | --- | --- |
| `q` | string | The search query, up to 500 characters |
| `hl` | string | Optional; the example request uses `en` |
| `start` | integer | Optional |
| `num` | integer | Optional |
| `as_ylo` | integer | Optional; the example request uses `2020` |
| `as_yhi` | integer | Optional |
| `scisbd` | integer | One of `0`, `1`, `2` |
| `cites` | string | Optional; see the `cites_id` note below |
| `cluster` | string | Optional |

The recorded request combines `hl`, `num` and `as_ylo`. For a loop that stops safely and doesn't double-bill, see [paginating a web data API in Python](https://perceptlayer.com/blog/paginate-web-data-api-python). The [search endpoint page](https://perceptlayer.com/apis/google-scholar/search) lists the same parameters.

## What does the search response contain?

The response wraps everything in `success` and `data`. Inside `data`, `search_parameters` echoes your inputs, `search_information` reports the totals, and `organic_results` holds the papers. Here's an excerpt of a recorded response for the request above:

```json
{
  "success": true,
  "data": {
    "search_parameters": {
      "engine": "google_scholar",
      "q": "machine learning",
      "hl": "en",
      "start": 0,
      "num": 10,
      "as_ylo": "2020",
      "scisbd": 0
    },
    "search_information": {
      "query_displayed": "machine learning",
      "total_results": 38300,
      "result_stats": "About 38,300 results (0.12 sec)"
    },
    "organic_results": [
      {
        "position": 1,
        "title": "Machine learning",
        "result_id": "WHD7vRZpYhIJ",
        …
        "publication_info": {
          "summary": "S Marsland - Computing Handbook, 2022 - api.taylorfrancis.com",
          …
        }
      },
      {
        "position": 2,
        "title": "Machine learning",
        "result_id": "K_YKyl3arXoJ",
        …
        "inline_links": {
          "cited_by": {
            "total": 292,
            "link": "https://scholar.google.com/scholar?cites=8839961739954681387&as_sdt=2005&sciodt=0,5&hl=en",
            "cites_id": "8839961739954681387"
          },
          …
        }
      }
    ]
  }
}
```

The fields you'll use most are listed here. Each one appears in the recorded response above.

| Field | What it holds |
| --- | --- |
| `position` | Rank of the result in the list |
| `title` | The paper or chapter title |
| `result_id` | Scholar's identifier for the result |
| `link` | URL of the paper or its host page |
| `snippet` | The text excerpt Scholar shows under the title |
| `publication_info.summary` | Authors, venue, year and host in one string |
| `inline_links.cited_by.total` | Citation count |
| `inline_links.cited_by.cites_id` | Identifier for the citing set |

Not every result has every field. In the recording, the first result has no `inline_links` block, while the second has `cited_by.total` set to 292. Read optional fields with a default instead of assuming they exist.

## How do you get citation counts from the response?

Read `inline_links.cited_by.total` on each entry in `organic_results`, and treat a missing block as "no count". In the recording, `cited_by.total` is the citation count field. This short script prints each title with its count and rank:

```python
import os
import requests

resp = requests.get(
    "https://api.perceptlayer.com/v1/google-scholar/search",
    params={"q": "machine learning", "hl": "en", "num": 10, "as_ylo": 2020},
    headers={"X-API-Key": os.environ["API_KEY"]},
    timeout=30,
)
resp.raise_for_status()

for item in resp.json()["data"]["organic_results"]:
    cited = item.get("inline_links", {}).get("cited_by", {}).get("total")
    print(item["position"], item["title"], cited)
```

Check `X-Credits-Used` and `X-Credits-Remaining` on the response if you track spend. A successful call reports 1 for the first. A failed call reports `X-Credits-Used: 0` and isn't billed.

### Follow a paper's citations with `cites`

The `cited_by.link` in the recording carries a `cites=` query value, and the same value appears as `cites_id`. The search endpoint has a `cites` parameter, typed as a string. The catalogue doesn't describe what it does, so try passing a `cites_id` there on one paper and inspect the response before you build a loop around it.

## What do the author, co-author, citation and cite endpoints do?

Four more endpoints cover authors, an author's citation entry and the cite lookup. We only have a recorded response for search, so this section lists their parameters, and the endpoint pages carry the details. All four take `GET` and cost 1 credit.

| Endpoint | Required | Optional |
| --- | --- | --- |
| [`/v1/google-scholar/author`](https://perceptlayer.com/apis/google-scholar/author) | `user` | `hl`, `num`, `start`, `sort` |
| [`/v1/google-scholar/author-citation`](https://perceptlayer.com/apis/google-scholar/author-citation) | `user`, `citation_id` | `hl` |
| [`/v1/google-scholar/author-co-authors`](https://perceptlayer.com/apis/google-scholar/author-co-authors) | `user` | `hl` |
| [`/v1/google-scholar/cite`](https://perceptlayer.com/apis/google-scholar/cite) | `q` | `hl` |

All three author endpoints require `user`. `sort` on the author endpoint accepts `title` or `pubdate`, and it also takes `num` and `start`. `author-citation` additionally requires a `citation_id`, and `cite` requires `q`. See the [author](https://perceptlayer.com/apis/google-scholar/author), [author-citation](https://perceptlayer.com/apis/google-scholar/author-citation), [author-co-authors](https://perceptlayer.com/apis/google-scholar/author-co-authors) and [cite](https://perceptlayer.com/apis/google-scholar/cite) pages for what each returns. A request for an author's co-authors looks like this, with your own `user` value:

```bash
curl "https://api.perceptlayer.com/v1/google-scholar/author-co-authors?user=USER_ID&hl=en" \
  -H "X-API-Key: $API_KEY"
```

Author profiles are personal data in the sense that they name real people. Use them for research and bibliometrics, and don't use them to contact people or build profiles without a lawful basis. Endpoints that return personal data can be restricted. If a call returns `restricted_endpoint` (403), accept the restricted-endpoint terms in the dashboard and retry.

## How much does a Google Scholar API call cost?

Every endpoint above costs 1 credit per successful call, and a failed call costs nothing. Credits are prepaid, so when your balance reaches zero the API returns `insufficient_credits` (402) and nothing more is debited. There's no automatic top-up. The [credits docs](https://docs.perceptlayer.com/credits) cover the headers, and the [pricing page](https://perceptlayer.com/pricing) shows what credits cost.

| Source of credits | Credits |
| --- | --- |
| Free tier | 1,000 every month |
| Starter pack | 10,000 |
| Build pack | 50,000 |
| Growth pack | 200,000 |

Larger packs (Pro, Scale and Volume) also exist, up to 5,000,000 credits. The free tier needs a verified email address and no credit card. Purchased credits last 12 months, with no subscription and no seats.

A worked example: a literature scan that runs 20 search calls, one per query, makes 20 calls × 1 credit = 20 credits, well inside the free tier. At 10,000 search calls a month you'd spend 10,000 calls × 1 credit = 10,000 credits, which equals one Starter pack. For what a pack costs, see [pricing](https://perceptlayer.com/pricing).

## What goes wrong, and how do you handle it?

Errors come back as an HTTP status and a JSON body shaped `{"error": {"code", "message", "request_id"}}`. The codes you're most likely to meet here are `invalid_api_key` (401), `invalid_parameters` (422), `rate_limited` (429), `source_error` (502) and `temporarily_unavailable` (503). The [errors docs](https://docs.perceptlayer.com/errors) list all of them.

For 429 and 503, read the `Retry-After` header and wait that many seconds. Requests have no idempotency key, so a call whose reply was lost to a client timeout may have succeeded and been billed. [Retrying web API calls without paying twice](https://perceptlayer.com/blog/retry-web-api-calls-without-paying-twice) covers how to handle that, and the [rate limit docs](https://docs.perceptlayer.com/rate-limits) give the limits.

If you're building an agent that looks up papers on demand, the same endpoints work through the MCP server. The `call_endpoint` tool takes an endpoint ID and its parameters. See [MCP server for web scraping](https://perceptlayer.com/blog/mcp-server-for-web-scraping) or the [MCP docs](https://docs.perceptlayer.com/ai-agents).

Next step: run the search call above in the [playground on the Google Scholar API page](https://perceptlayer.com/apis/google-scholar), then copy the cURL into your own script.

## APIs in this post

-   [Google Scholar **1 credit per call** · 5 endpoints](https://perceptlayer.com/apis/google-scholar)

## Frequently asked questions

### Does Google Scholar have an official API?

Google's Scholar about page doesn't mention one, though we can't prove none exists. To get results and citation counts as JSON, you call a service that returns them as fields. The Perceptlayer Google Scholar API exposes five endpoints for this, and each successful call costs 1 credit.

### How much does the Google Scholar API cost?

Each successful call to any of the five endpoints costs 1 credit, and failed calls cost nothing. The free tier gives 1,000 credits every month after you verify an email. Paid packs start at 10,000 credits (the Starter pack), so 10,000 calls × 1 credit = 10,000 credits. See [pricing](https://perceptlayer.com/pricing) for what credits cost.

### Is there an endpoint for authors and co-authors?

Yes, there are two, though we have no recorded response for them. The `author` endpoint takes a required `user` and optional `hl`, `num`, `start` and `sort` ( `title` or `pubdate`). The `author-co-authors` endpoint takes `user` and optional `hl`. Each call costs 1 credit. Use them for research, and not to contact people.

### How do I filter Google Scholar results by year?

Pass `as_ylo` for the earliest year and `as_yhi` for the latest on the search endpoint. Both are integers. The recorded request above used `as_ylo=2020`, and the response echoed it back inside `search_parameters`. Filtering doesn't change the price: the call still costs 1 credit.

### What happens if a call fails?

You get an HTTP status and a JSON error with a `code`, `message` and `request_id`. Failed calls return `X-Credits-Used: 0` and aren't billed. For 429 and 503, wait the number of seconds in `Retry-After`. If a client timeout hid the reply, the call may still have been billed.

google scholar citations academic search research data search engines

## More from the blog

1.  [API guides](https://perceptlayer.com/blog/category/api-guides) 23 Oct 2026 Perceptlayer 7 min read
    
    ## [Cars.com API: Used Car Listings and Price Evaluations](https://perceptlayer.com/blog/cars-com-api-listings-price-evaluation)
    
    Search Cars.com listings with its six required parameters (zip, radius\_miles, stock\_type, sort, page, page\_size), then listing, dealer and price-eval calls.
    
2.  [API guides](https://perceptlayer.com/blog/category/api-guides) 22 Oct 2026 Perceptlayer 7 min read
    
    ## [Booking.com Reviews API: Hotel Review Scores as JSON](https://perceptlayer.com/blog/booking-com-reviews-api-json)
    
    Pull Booking.com review scores and guest reviews as JSON with two GET calls at 1 credit each. Parameters, sorting, paging and the cost of covering a city.
    
3.  [API guides](https://perceptlayer.com/blog/category/api-guides) 22 Oct 2026 Perceptlayer 9 min read
    
    ## [Idealo API: Compare Product Prices Across Shops as JSON](https://perceptlayer.com/blog/idealo-api-price-comparison-json)
    
    Search idealo.de by keyword, then pass a product\_id to the offers endpoint. Endpoints, parameters, a real search response and the cost at 1 credit per call.
