# Google Patents Scraper - Search & Full Records (`s-r/google-patents`) Actor

Search the Google Patents index by keyword, assignee, inventor, country, date window and grant status, or read patents in full: every inventor, the four dates kept apart, classifications, claim count and how many later patents cite it.

- **URL**: https://apify.com/s-r/google-patents.md
- **Developed by:** [SR](https://apify.com/s-r) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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 Patents Scraper - Search & Full Records

Search the Google Patents index the way the site itself does, or read patents
in full: every inventor, all four dates kept apart, classifications, claim
count and how many later patents cite the thing.

No API key, no browser, no login.

### Two modes

**Search** walks the index and returns a row per hit, a hundred results per
request. Filter by keyword, assignee, inventor, country, date window, grant
status, document type, and sort by relevance or by date.

**Detail** takes publication numbers you already have and returns the full
record for each.

Tick **Read each result in full** and search runs into detail automatically,
which is how you get from a keyword to complete records without pasting
numbers by hand.

### Four dates, and they are not the same date

A patent carries four, they all read as "the date", and most tools flatten
them into one:

| | priority | filing | publication | grant |
|---|---|---|---|---|
| US6285999B1 (PageRank) | 1997-01-10 | 1998-01-09 | 2001-09-04 | 2001-09-04 |
| EP1000000A1 | 1998-11-12 | 1999-11-08 | 2000-05-17 | *none* |
| US20250259144A1 | 2024-02-08 | 2024-06-04 | 2025-08-14 | *none* |

A year between priority and filing is normal, and priority is the one that
decides who was first. **`grant_date` stays empty on anything that was never
granted.** Filling it from the publication date would turn every pending
application in your export into a granted patent, silently.

### Every inventor, not the first one

The search index publishes **one** inventor per patent. That is a real limit of
that endpoint, not a choice, and it is why the two modes return different
fields:

| | search row | read in full |
|---|---|---|
| inventor | `Ali Kanso` | `Ali Kanso, Muhammed Fatih Bulut, Jinho Hwang, Shripad Nadgowda` |

Both are on the row and they are named differently, `inventor` and `inventors`,
so nothing has to be guessed from context.

### Counts that are actually counts

**`cited_by` is uncapped.** The PageRank patent returns **1,658** later patents
citing it. That is the field that tells you a patent matters, so it had to be a
real number rather than a page of results.

**Similar documents is not published.** It stops at about 25 on every patent,
including the one with 1,658 citations, so it is a page size wearing a count's
clothes.

**Claim counts come from Google's own heading.** Counting claim elements
returns 20 on one patent office's markup and 0 on another's. Google prints the
number itself, so that is what gets used: 20, 11, 29, 3 across the four offices
in the test set.

**Classifications have their parents removed.** Codes arrive as a chain, G then
G01 then G01S then G01S7/48. Counted raw that is 47 classifications for a
patent that has 15.

**Patent citations and non-patent citations are separate columns.** The papers
and books an examiner cited are a different thing from the patents cited, and
adding them together is how you get a number that matches nobody else's.

### What you get

| field | search | in full |
|---|---|---|
| `publication_number`, `title`, `url` | yes | yes |
| `snippet` (the matched passage) | yes | — |
| `inventor`, `assignee` (first of each) | yes | yes |
| `priority_date`, `filing_date`, `publication_date`, `grant_date` | yes | yes |
| `figure_count`, `pdf_url` | yes | yes |
| `abstract`, `status` | — | yes |
| `inventors`, `assignees` (complete) | — | yes |
| `application_number`, `claims_count` | — | yes |
| `cpc_codes`, `cpc_count` | — | yes |
| `patent_citations`, `non_patent_citations`, `cited_by` | — | yes |

`status` is Google's: `Active`, `Pending`, `Expired - Lifetime`,
`Expired - Fee Related`.

### Input

```json
{ "query": "machine learning", "max_results": 100 }
```

Everything a company has filed since 2024, granted only, newest first:

```json
{
  "query": "neural network",
  "assignee": "Google LLC",
  "after": "priority:20240101",
  "status": "GRANT",
  "sort": "new",
  "max_results": 200
}
```

An inventor's whole output, read in full:

```json
{ "inventor": "Joseph Marron", "follow_details": true }
```

Specific patents:

```json
{ "mode": "detail", "publication_numbers": ["US10000000B2", "EP1000000A1"] }
```

Publication numbers accept full Google Patents URLs too, so a list pasted out
of a browser works without cleaning it up first.

### About the assignee filter

Google matches **corporate families**, not exact strings. Searching
`Google LLC` also returns X Development LLC and the same company's filings
under its Japanese-script name. That is usually what you want from a competitor
sweep and occasionally a surprise, so the assignee Google recorded is on every
row and you can filter afterwards on what actually came back.

Google also attaches its own caveat to assignee data, that the listed assignees
may be inaccurate and it has performed no legal analysis. That caveat travels
with the field. This Actor reports what Google publishes.

### Pricing

Pay per event.

| event | price |
|---|---|
| Run start | $0,002 |
| Patent found (search row) | $0,002 |
| Patent read in full | $0,005 |

A search row and a full record cost very different amounts to produce: one
request returns a hundred search rows, one request returns one full record.
Charging them the same would either make a large search absurd or sell full
records below cost.

A 100-patent search bills **$0,202**. The same search reading every result in
full bills **$0,502**. Ten patents read in full bills **$0,052**.
`max_results` is a hard ceiling, so a run cannot cost more than you decided in
advance. **A patent whose page could not be read bills as a search row, not as
a full record**, because you did not get one.

### Limits, stated plainly

- **Search rows carry one inventor and one assignee.** That is what the index
  publishes. Turn on `follow_details` for the complete lists.
- **The result total is an estimate.** Google reports 119,420 for a bare query
  and 120,421 for the same query restricted to one country. A restriction
  cannot widen a result set, so the number is reported as
  `estimatedTotalResults` and never as a total. The rows themselves are real
  and were checked against the filters that produced them.
- **Volume is throttled.** Sustained reading gets an HTTP 503 refusal. Requests
  are retried and the summary reports `requestsThrottled` so a short run is
  explainable rather than mysterious. A throttled request is never reported as
  a patent that does not exist.
- **Not every field exists on every patent.** Design patents carry no
  classifications, Chinese patents in the test set carried no cited references,
  applications carry no grant date. Those come back empty rather than filled in
  from something nearby, and any field that resolved on **no row at all** is
  named in the run summary under `fieldsThatDidNotResolve`.
- **Abstracts and claim counts, not full claim text.** The record is the
  metadata layer. The `pdf_url` on each row is the document itself.

### Output

Rows go to the default dataset. The run summary and any errors go to the
default key-value store as `summary` and `errors`. The summary carries the
mode, rows returned, search and detail request counts, retries, throttles, and
the list of fields that never resolved, so a run can be judged without reading
the rows.

# Actor input Schema

## `mode` (type: `string`):

Search walks the index and returns a row per hit, a hundred per request. Detail reads publication numbers you already have and returns the full record for each.

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

Search terms, as you would type them into Google Patents. Leave empty if you are searching by assignee or inventor alone.

## `assignee` (type: `string`):

Company the patent is assigned to. Google matches corporate families, so Google LLC also returns X Development and the Japanese-script filings of the same company.

## `inventor` (type: `string`):

Inventor name. Works on its own without a keyword.

## `country` (type: `string`):

Two-letter patent office code, such as US, EP, CN, DE, JP. Leave empty for every office.

## `after` (type: `string`):

A date floor written as Google writes it: priority:20240101, filing:20200101 or publication:20230101.

## `before` (type: `string`):

A date ceiling in the same form, such as priority:20200101.

## `status` (type: `string`):

GRANT returns granted patents, APPLICATION returns filings that have not been granted.

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

PATENT for utility patents, DESIGN for design patents.

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

Relevance is Google's ranking. New and old sort by publication date, which is how you get the most recent filings in a field.

## `max_results` (type: `integer`):

Stop after this many patents. Also the cost ceiling for the run.

## `follow_details` (type: `boolean`):

After searching, open every result and add the full record: every inventor rather than the first, classifications, claim count and citation counts. This costs one extra request per patent, so it is off by default.

## `publication_numbers` (type: `array`):

Detail mode only. One per line, such as US10000000B2 or EP1000000A1. Full Google Patents URLs are accepted too.

## `language_page` (type: `string`):

Which translation of the patent page to read. Two letters, such as en or de.

## `attempts` (type: `integer`):

How often to retry a request that fails. Google throttles by volume, and a retry usually clears it.

## Actor input object example

```json
{
  "mode": "search",
  "query": "solid state battery",
  "assignee": "Google LLC",
  "inventor": "Joseph Marron",
  "country": "US",
  "after": "priority:20240101",
  "before": "publication:20241231",
  "status": "ANY",
  "type": "ANY",
  "sort": "relevance",
  "max_results": 100,
  "follow_details": false,
  "publication_numbers": [
    "US6285999B1"
  ],
  "language_page": "en",
  "attempts": 3
}
```

# Actor output Schema

## `patents` (type: `string`):

One row per patent.

## `summary` (type: `string`):

Mode, rows returned, requests sent and retried, and any field that resolved on no row at all.

## `errors` (type: `string`):

Searches and patents that could not be read.

# 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": "machine learning",
    "publication_numbers": [
        "US10000000B2"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("s-r/google-patents").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": "machine learning",
    "publication_numbers": ["US10000000B2"],
}

# Run the Actor and wait for it to finish
run = client.actor("s-r/google-patents").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": "machine learning",
  "publication_numbers": [
    "US10000000B2"
  ]
}' |
apify call s-r/google-patents --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,s-r/google-patents"
        }
    }
}
```

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/292W53TQ6GbS5xxgg/builds/E4bIqHyaNRafxw6qM/openapi.json
