# Google Patents Scraper & API - US Patent Search by Company (`s-r/google-patents`) Actor

Search USPTO, EPO, WIPO and worldwide patents on Google Patents by keyword, company, inventor, country or date window, or read patents in full: every inventor, four dates, CPC codes, claims, citations and how many later patents cite it. For IP teams, competitor watch and prior art research.

- **URL**: https://apify.com/s-r/google-patents.md
- **Developed by:** [SR](https://apify.com/s-r) (community)
- **Categories:** Business, Developer tools, Automation
- **Features:** Limited permissions
- **Stats:** 9 total users, 7 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 run starts

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?

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

## Google Patents API - Patent Search & Full Records

This Google Patents API gives you patent search and full patent records as
clean JSON or CSV: search the Google Patents index the way the site itself
does, or read patents in full, with 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. Built for IP and patent teams, competitor
watch, prior art research, analysts and anyone who needs Google Patents data in
a spreadsheet or a pipeline instead of a browser tab.

### 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.

### What the Google Patents API returns

#### 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.

### Input

The simplest Google Patents search, a keyword and a ceiling:

```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"] }
```

A date window on its own office, the way a prior art search starts: Toyota's
granted Japanese solid state battery patents with a priority date in
2010–2014, oldest first, read in full. A real run of exactly this input
returned 12 full records, the first one `JP5445146B2` with priority date
2010-01-06:

```json
{
  "query": "solid state battery",
  "assignee": "Toyota",
  "country": "JP",
  "after": "priority:20100101",
  "before": "priority:20141231",
  "status": "GRANT",
  "type": "PATENT",
  "sort": "old",
  "max_results": 12,
  "follow_details": true
}
```

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

| input | what it does | default |
|---|---|---|
| `mode` | `search` or `detail` | `search` |
| `query` | keywords, as typed into Google Patents | — |
| `assignee` | company or owner (patent search by company) | — |
| `inventor` | inventor name (patent search by inventor) | — |
| `country` | patent office code, e.g. `US`, `EP`, `JP`, `CN` | — |
| `after`, `before` | date window, e.g. `priority:20240101` | — |
| `status` | `ANY`, `GRANT`, `APPLICATION` | `ANY` |
| `type` | `ANY`, `PATENT`, `DESIGN` | `ANY` |
| `sort` | `relevance`, `new`, `old` | `relevance` |
| `max_results` | hard ceiling on rows, 1–5000 | `100` |
| `follow_details` | read every search result in full | `false` |
| `publication_numbers` | numbers or URLs for mode `detail` | — |
| `language_page` | language of the detail page | `en` |
| `attempts` | tries per request, 1–10 | `3` |

#### 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.

### 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.

| 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 |
| `language`, `position` | yes | yes |
| `query` (the search that produced the row) | yes | — |
| `record_kind` (`patent` or `patent_detail`) | yes | yes |
| `cited_by_count` (same number as `cited_by`) | — | yes |
| `source`, `engine`, `fetched_at` | yes | yes |
| `search_row_count`, `detail_row_count` (1 or 0) | yes | yes |

`record_kind` says what a row is and therefore what it was billed as: a
`patent` row is a search hit, a `patent_detail` row is a full record. The two
row-count fields say the same thing as numbers, so a spreadsheet can sum them.

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

#### Example search row

From a real run with `{"query": "machine learning"}`, the first of 100 rows:

```json
{
  "publication_number": "US12438891B1",
  "title": "Anomaly detection based on ensemble machine learning model",
  "snippet": "accessing the entity profile to read the plurality of features scores for the entity; processing the plurality of feature scores for the entity, accessed from the entity profile, by using a plurality of machine-learning models; generating a plurality of intermediate anomaly scores for the entity, …",
  "inventor": "Sudhakar Muddu",
  "assignee": "Splunk Inc.",
  "priority_date": "2015-08-31",
  "filing_date": "2022-02-18",
  "publication_date": "2025-10-07",
  "grant_date": "2025-10-07",
  "language": "en",
  "figure_count": 116,
  "pdf_url": null,
  "url": "https://patents.google.com/patent/US12438891B1/en",
  "query": "q=(machine+learning)",
  "position": 1
}
```

#### Example full record

From a real run with `{"mode": "detail", "publication_numbers": ["US10000000B2"]}`
(abstract shortened here):

```json
{
  "publication_number": "US10000000B2",
  "url": "https://patents.google.com/patent/US10000000B2/en",
  "title": "Coherent LADAR using intra-pixel quadrature detection",
  "abstract": "A frequency modulated (coherent) laser detection and ranging system includes a read-out integrated circuit …",
  "status": "Active",
  "inventors": ["Joseph Marron"],
  "assignees": ["Raytheon Co"],
  "application_number": "US:14/643,719",
  "priority_date": "2015-03-10",
  "filing_date": "2015-03-10",
  "publication_date": "2018-06-19",
  "grant_date": "2018-06-19",
  "claims_count": 20,
  "cpc_codes": ["G01S13/00", "G01S13/88", "G01S13/89", "G01S17/00", "G01S17/88", "G01S17/894", "G01S7/00", "G01S7/483", "G01S7/4861", "G01S7/4863", "G01S7/4865", "G01S7/4912", "G01S7/4913", "G01S7/4914", "G01S7/4917"],
  "cpc_count": 15,
  "patent_citations": 5,
  "non_patent_citations": 7,
  "cited_by": 22,
  "pdf_url": "https://patentimages.storage.googleapis.com/c0/d5/f7/86ad5b42759506/US10000000.pdf",
  "language": "en",
  "position": 1
}
```

### Use cases

- **Competitor watch.** Run an assignee search with `sort: new` every week and
  see what a rival filed, granted or abandoned since the last export.
- **Prior art search.** Search a concept with a `before` date and read the hits
  in full, with abstracts, classifications and citation counts side by side.
- **Inventor and talent mapping.** A patent search by inventor returns their
  whole output, and the full records name every co-inventor and employer.
- **Portfolio analysis.** Feed a list of publication numbers and get status,
  grant date, claim count and `cited_by` for each, ready for a spreadsheet.
- **Landscaping and research.** Pull a few thousand rows on a technology,
  group them by CPC code, country and priority year.

### Google Patents API compared with the alternatives

| | this Actor | Google Patents website | public patent datasets | other patent search APIs |
|---|---|---|---|---|
| bulk export | yes, up to 5000 rows per run | by hand | yes | yes |
| setup | none | none | a cloud account and SQL | an account and a key |
| every inventor, four dates | yes | on each page | yes | varies |
| uncapped `cited_by` count | yes | on each page | yes | varies |
| pay per patent | yes | free, but manual | pay per query scanned | usually a monthly plan |

The website is the right tool for reading one patent. This Actor is for the
moment you need fifty, or five thousand, in a table, with the filters of the
Google Patents advanced search and nothing to install.

### 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. A search that finds nothing
returns an empty, successful run and bills only the run start. Every row
carries `record_kind`, so you can check the bill against the dataset yourself.

**Free plan.** On a free Apify plan a run delivers at most 10 rows and bills
only those 10. Paid plans get the full `max_results`.

### 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.

### FAQ

**Is there an official Google Patents API?**
Google does not offer a public REST API for patents.google.com. This Actor
works as one: send a search or a list of numbers, get JSON back.

**Can I search patents by company or by inventor?**
Yes. Fill `assignee` for a patent search by company and `inventor` for a patent
search by inventor; both work without a keyword and combine with country, date
and status filters.

**Which patent offices are covered?**
Everything the Google Patents index holds, including US, EP, WO, JP, CN, KR and
DE publications. Use `country` to restrict a search to one office.

**Why is `grant_date` empty on some rows?**
Because the document is an application that was never granted. The date is
left empty rather than borrowed from the publication date.

**How do the date filters work?**
`after` and `before` take a date type and a date, written as
`priority:20240101`. The date type is `priority`, `filing` or
`publication`, the same choices as the Google Patents advanced search. Combine
both for a window; they work with every other filter.

**How many results can one run return?**
Up to 5000 search rows, set with `max_results`. Reading every result in full
takes one request per patent, so large detail runs take longer.

**Do I need a Google account or an API key?**
No. You only need an Apify account; the run uses public Google Patents pages.

# 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/GvMG2wYO4eoxCNI6M/openapi.json
