# USPTO Trademark Scraper - Search, Owners, Status & Classes (`scrapewise/uspto-trademark-scraper`) Actor

Search US trademarks (USPTO) without an API key: by mark, owner, goods and services, serial or registration number. Status, classes, dates, owners, attorney, image. Name availability check, Nice class suggestions, renewal deadlines, monitoring of new filings and past 10,000 results per search.

- **URL**: https://apify.com/scrapewise/uspto-trademark-scraper.md
- **Developed by:** [Scrapewise Data](https://apify.com/scrapewise) (community)
- **Categories:** Lead generation
- **Stats:** 2 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.70 / 1,000 trademark delivereds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## USPTO Trademark Scraper: US trademark search, owners, status, classes and availability

Search the **United States Patent and Trademark Office (USPTO)** trademark register **without an API key, an account
or a browser**. Type a word ("coffee", "blue bottle"), an owner ("Starbucks Corporation"), a product in the goods
and services ("energy drinks"), or paste serial and registration numbers, and get one row per trademark with
**mark text, status (live or dead), serial and registration numbers, filing, registration, publication and
abandonment dates, Nice classes, full goods and services, current and original owner, attorney of record,
disclaimer, design codes, filing basis and a link to the mark image**. Plus a **name availability check**,
**Nice class suggestions**, **renewal and Section 8 deadlines** and **monitoring of new filings**.

Built for trademark attorneys and paralegals, brand managers watching new filings, founders checking a name before
filing, and IP analytics and lead generation teams.

### At a glance

| Event | Per 1,000, Free plan | Bronze | Silver | Gold and up |
|---|---|---|---|---|
| Trademark delivered, until 30 Oct 2026 | US$ 2.00 | US$ 2.00 | US$ 2.00 | US$ 2.00 |
| Trademark delivered, **from 31 Oct 2026** | **US$ 5.00** | US$ 4.75 | US$ 4.50 | US$ 4.25 |

- **51 fields per trademark row**, among them `status`, `live`, `registered`, every key date, `internationalClasses`,
  `goodsAndServices` per class, `owners` with role and entity type, `attorneyName`, `designCodes`, `affidavits`,
  `imageUrl` and `tsdrUrl`. All of them are in the [field reference](#field-reference).
- **No start fee, no monthly fee.** Error rows, duplicates and marks outside your filters are free, and `maxItems`
  is a hard stop.
- **Past the 10,000-result cap** of the USPTO search screen: up to 100,000 marks per search, split by filing date
  for you.
- **Monitoring that does not charge twice:** only new marks and status changes since the last run.
- **Resumes after a platform restart** without charging twice.

### What you can do with it

- **Clearance search:** every live mark with "blue bottle" in coffee and restaurant classes, with owner and status.
- **Check if a name is free:** `operation: "availability"` gives one row per name with `available`, a `verdict`
  (available, similar marks exist, taken), the identical live marks and the 10 closest live marks.
- **Watch new filings:** new "energy drinks" applications every week, to review or oppose; unchanged marks are free.
- **Renewal and Section 8 leads:** `operation: "expiring"` lists live registrations whose maintenance deadline falls
  in a window up to one year, with the deadline, its type and the end of the grace period.
- **Pick the right class:** `operation: "suggestClass"` shows the classes live US marks use for your goods, with an
  example description for each.
- **Map a portfolio or refresh a docket:** every mark of an owner, or hundreds of serial numbers at once.
- **Build lead lists:** new company applicants in a class, with the business address on the register and the
  attorney of record.

### Input examples

An empty input runs a small example (20 trademarks for "coffee"), so the Actor never fails on a blank form.

Every live coffee mark filed by a company in 2025:

```json
{
  "searchTerms": ["coffee"],
  "status": "live",
  "internationalClasses": ["30"],
  "filedFrom": "2025-01-01",
  "filedTo": "2025-12-31",
  "excludeIndividualOwners": true,
  "maxResultsPerSearch": 2000
}
```

Clearance for an exact phrase in two classes:

```json
{ "searchTerms": ["blue bottle"], "exactPhrase": true, "status": "live", "internationalClasses": ["30", "43"] }
```

Weekly watch of new "energy drinks" filings, delivering only what is new:

```json
{ "goodsAndServices": ["\"energy drinks\""], "sortBy": "newest", "monitorMode": true, "monitorKey": "energy-drinks" }
```

A competitor's portfolio:

```json
{ "ownerNames": ["Starbucks Corporation"], "maxResultsPerSearch": 500 }
```

Availability, class suggestion and renewal deadlines:

```json
{ "operation": "availability", "searchTerms": ["blue bottle"], "internationalClasses": ["30"] }
```

```json
{ "operation": "suggestClass", "goodsAndServices": ["scented candles"] }
```

```json
{ "operation": "expiring", "startDate": "2026-11-01", "endDate": "2026-11-30" }
```

| Field | What it does |
|---|---|
| `searchTerms` | Words in the mark, one search per line. All words must appear; quotes for a phrase, `*` wildcard, `|` for OR, `-` to exclude. |
| `ownerNames` | Owner (applicant or registrant) names, one per line. |
| `goodsAndServices` | Words in the goods and services description, one search per line. |
| `serialNumbers` / `registrationNumbers` | Numbers, one per line or comma separated. |
| `startUrls` | TSDR case links or `tmsearch.uspto.gov` search links with `?query=`. |
| `status`, `registeredOnly` | `all` (default), `live` or `dead`; only marks that reached registration. |
| `internationalClasses` | Nice classes (30, 43, IC 030...). Empty = all. |
| `filedFrom` / `filedTo` | Filing date range (2024-01-01, or a year like 2024). |
| `exactPhrase` | Mark words in this exact order. |
| `excludeIndividualOwners` | Skip marks owned by individuals or sole proprietors. |
| `excludeKeywords` | Skip marks whose text has any of these words (free). |
| `sortBy` | `relevance` (default), `newest`, `oldest`, `recentlyRegistered`. |
| `maxResultsPerSearch` / `maxItems` | Trademarks per search (default 100, up to 100,000); hard cap for the run. |
| `operation` | Empty = search. `availability`, `suggestClass` or `expiring`. |
| `startDate` / `endDate` | Deadline window for `expiring` (up to one year; empty = the next 30 days). |
| `monitorMode`, `monitorKey`, `alertOnStatusChange` | Only marks new or changed since the last run with the same key; status changes on by default. |

#### Switching from another USPTO trademark actor? Your input works

`terms`, `queries`, `query` and `keywords` are read as `searchTerms`; `liveDead` and `statusFilter` as `status`;
`exactOnly` and `exactMatch` as `exactPhrase`; `classes` (`"25,9"`), `niceClasses` and `"IC 025"` as
`internationalClasses`; `filedAfter` / `filedBefore` as the filing range; `maxResultsPerQuery`, `maxResults` as the
limits; `ownerName` as an owner filter; `watchMode` or `mode: "watch"` with `watchLabel` as monitoring. Operations
`search`, `details`, `ownerSearch`, `fullText`, `owner-search`, `goods-services-search` and `serial-lookup` map to the
matching field. `offices` with `US` is accepted; other offices get a free `INVALID_INPUT` row.

### Output

One real row from a test run on 2026-09-30 (search "blue bottle", exact phrase, live, class 30; goods text and
owners shortened, empty fields left out):

```json
{
  "type": "trademark",
  "serialNumber": "88471899",
  "registrationNumber": "6125844",
  "markText": "BLUE BOTTLE COFFEE",
  "markType": "TRADEMARK",
  "status": "REGISTERED",
  "statusCode": 700,
  "live": true,
  "registered": true,
  "filingDate": "2019-06-13",
  "registrationDate": "2020-08-11",
  "publishedForOppositionDate": "2019-10-15",
  "firstUseInCommerceDate": "2002-08-15",
  "internationalClasses": [30],
  "goodsAndServices": [
    {"class": 30, "description": "Ground and whole bean coffee; coffee and espresso beverages; ready-to-drink coffee; tea; ...", "cancelled": false}
  ],
  "ownerName": "BLUE BOTTLE GLOBAL HOLDINGS LIMITED",
  "ownerCountry": "HONG KONG",
  "originalOwnerName": "Blue Bottle Coffee, LLC",
  "owners": [
    {"name": "BLUE BOTTLE GLOBAL HOLDINGS LIMITED", "entityType": "PRIVATE LIMITED COMPANY", "isIndividual": false,
     "citizenship": "HONG KONG", "role": "SUBSEQUENT OWNER AFTER REGISTRATION", "city": "CENTRAL",
     "stateCountry": "HONG KONG", "address": "29/F ONE EXCHANGE SQUARE 8, CONNAUGHT PLACE, CENTRAL, HONG KONG", "dba": null}
  ],
  "attorneyName": "Christopher M. Kindel",
  "disclaimer": "\"COFFEE\"",
  "filingBasisCurrent": ["1A"],
  "assignmentRecorded": true,
  "imageUrl": "https://tsdr.uspto.gov/img/88471899/large",
  "tsdrUrl": "https://tsdr.uspto.gov/#caseNumber=88471899&caseSearchType=US_APPLICATION&caseType=DEFAULT&searchType=statusSearch",
  "source": "mark:blue bottle",
  "errorCode": null
}
```

Availability of "blue bottle" in class 30 on 2026-10-08: `verdict` "similar marks exist", `available` true,
0 identical live marks, 5 live and 3 dead marks containing the name, and BLUE BOTTLE COFFEE (88471899) first in
`conflictingMarks`. For "scented candles", `suggestClass` puts class 4 first (97.1% of 300 live marks read). Each availability or class suggestion row is charged like one
trademark.

<a id="field-reference"></a>

### Field reference

**Trademark** (`type: trademark`):

| Field | What it is |
|---|---|
| `serialNumber`, `registrationNumber`, `internationalRegistrationNumber` | USPTO numbers and the Madrid number when there is one |
| `markText`, `markTextPseudo`, `markType`, `drawingType`, `standardCharacters`, `markDescription` | the mark and how it is drawn |
| `status`, `statusCode`, `live`, `registered`, `register` | status text and code, live/dead, registered, Principal or Supplemental |
| `filingDate`, `registrationDate`, `publishedForOppositionDate`, `abandonedDate`, `cancelledDate`, `renewalDate`, `priorityDate`, `firstUseDate`, `firstUseInCommerceDate` | every key date (`YYYY-MM-DD`, `null` when empty) |
| `internationalClasses`, `usClasses` | Nice classes and old US classes |
| `goodsAndServices`, `goodsAndServicesText` | per class description (with `cancelled`), and one text |
| `ownerName`, `ownerEntityType`, `ownerCountry` | the **current** owner (the last one after an assignment) |
| `originalOwnerName`, `owners` | the applicant, and every owner with role, entity type, citizenship, city and address |
| `attorneyName` | attorney of record, by name only |
| `disclaimer`, `translation`, `transliteration`, `designCodes` | disclaimed words, translation, design search codes |
| `filingBasisCurrent`, `filingBasisOriginal` | USPTO codes: 1A use in commerce, 1B intent to use, 44D/44E foreign, 66A Madrid |
| `affidavits`, `assignmentRecorded` | Section 8, 15 and similar filings; whether an assignment is recorded |
| `imageUrl`, `tsdrUrl` | USPTO image of the mark (PNG) and the TSDR case page |
| `position`, `searchType`, `searchQuery`, `source` | where the row came from |

With `operation: "expiring"` a row adds `maintenanceDueDate`, `maintenanceType` (`Section 8 declaration (6th
year)` or `Renewal, Sections 8 and 9 (10th year)`) and `gracePeriodEnds`. With `monitorMode` it adds `changeType`
(`new` or `statusChanged`), `previousStatus` and `firstMonitorRun`.

**Availability** (`type: availability`): `searchQuery`, `verdict`, `available`, `identicalLiveMarks`,
`liveMarksContainingName`, `deadMarksContainingName`, `classesChecked`, `takenInClasses`, `conflictingMarks`, `note`.

**Class suggestion** (`type: classSuggestion`): `searchQuery`, `topClass`, `suggestedClasses` (class, code, title,
share, live marks, example description), `sampleSize`, `liveMarksMatching`, `note`.

Every row also has `scrapedAt`, `errorCode` and `error`. The run also saves `SEARCH_SUMMARY` in its key-value store:
for each search, how many marks the USPTO has, how many pages were read and how many rows were delivered.

#### Error rows (never charged)

| errorCode | When |
|---|---|
| `NO_RESULTS` | No trademark matches the search with your filters. |
| `NOT_FOUND` | A serial or registration number does not exist. |
| `INVALID_URL` | The link is not a TSDR or Trademark Search link. |
| `BLOCKED` | The USPTO refused every attempt for that search. |
| `INVALID_INPUT` | A field has a value the Actor cannot use (the message says which). |
| `UNEXPECTED` | Anything else; the rest of the run continues. |

### Pricing examples

| | Until 30 Oct 2026 | From 31 Oct 2026, Free plan |
|---|---|---|
| 1,000 trademarks | US$ 2.00 | US$ 5.00 |
| A 250-mark portfolio | US$ 0.50 | US$ 1.25 |
| One availability check | US$ 0.002 | US$ 0.005 |

### Integrations, scheduling and AI agents

- **Schedule** a weekly watch in [Apify schedules](https://docs.apify.com/platform/schedules) with `monitorMode`
  and a `monitorKey`; unchanged marks are free.
- **Export** as JSON, CSV, Excel or XML, or read the dataset from the [Apify API](https://docs.apify.com/api/v2).
- **Connect** it to Make, n8n, Zapier, Google Sheets or a webhook through
  [Apify integrations](https://docs.apify.com/platform/integrations), for example "email me every new filing in
  class 32 that contains our brand".
- **AI agents:** the Actor works as a tool through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp)
  in Claude, ChatGPT, Cursor and other MCP clients, for example "is the name Nordbrew free for beer in class 32?".

### How it works and limits

- It reads the public index behind the USPTO Trademark Search (tmsearch.uspto.gov) over plain HTTP, through the
  Apify datacenter proxy (a US residential IP only as a reserve).
- The index returns at most 10,000 marks per query. Past that, the Actor splits the search by filing year (and by
  month when needed), newest first. In our tests 10,300 "coffee" marks came in about 8 minutes; 250 marks take 3
  to 30 seconds.
- **Personal data.** For owners that are individuals or sole proprietors the Actor returns only city, state and
  country: no street address and no ZIP code. Company owners come with the business address on the register.
  Email addresses are never returned.

### FAQ

**Do I need a USPTO account or API key?** No.

**Can I get the full prosecution history and documents?** Not in this version: each row has the status, dates and
the TSDR link where the documents live.

**Can I monitor new filings?** Yes: `monitorMode: true` and a `monitorKey` on a schedule. Each later run delivers
only new marks and status changes.

**Is "available" a legal opinion?** No. It means no live mark on the USPTO register has the identical name (in your
classes, when you give them). Similar marks, foreign registrations and unregistered rights are not checked; talk to
a trademark attorney before filing.

**What changes on 31 Oct 2026?** Only the price per 1,000 trademarks (table above). Runs before that date pay
US$ 2.00 per 1,000; input, output and free error rows stay the same.

### Changelog

- **16 Oct 2026:** new prices from 31 Oct 2026 shown, field reference, ready-to-run input examples and an
  integrations section in this page.
- **0.1 (8 Oct 2026):** input of other USPTO actors works as is; `availability`, `suggestClass` and `expiring`
  operations; monitoring with only new and changed marks; `ownerName` filter.
- **0.1 (30 Sep 2026):** first version: mark, owner, goods and services and number searches, TSDR and search links,
  live/dead, class, date and company-only filters, more than 10,000 per search, resume after restart.

Independent tool, not affiliated with the United States Patent and Trademark Office.

# Actor input Schema

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

Leave empty for a normal search. 'availability' gives one row per name with available / taken / similar marks exist, the identical live marks and the classes they cover. 'suggestClass' gives the Nice classes used by live marks with those goods. 'expiring' lists live registrations whose renewal or Section 8 deadline falls between startDate and endDate.

## `searchTerms` (type: `array`):

Words in the trademark itself, one search per line (for example: coffee, blue bottle, "air max"). All words must appear; use quotes for an exact phrase, \* as a wildcard (coff\*), | for OR and - to exclude a word. Searches the mark text and USPTO's pseudo-mark spelling variants.

## `ownerNames` (type: `array`):

Company or owner names, one per line (for example: Starbucks Corporation, Nike). Returns the trademarks filed by or assigned to that owner, as the USPTO record names it.

## `goodsAndServices` (type: `array`):

Words in the goods and services description, one search per line (for example: "roasted coffee", energy drinks). Useful to map every mark filed for a product type; combine with classes and dates.

## `serialNumbers` (type: `array`):

USPTO serial numbers (8 digits, for example 97123456), one per line or separated by commas. Each number returns its full record; numbers that do not exist come back as a free NOT_FOUND row.

## `registrationNumbers` (type: `array`):

USPTO registration numbers (for example 5511206), one per line or separated by commas.

## `startUrls` (type: `array`):

TSDR case links (https://tsdr.uspto.gov/#caseNumber=97123456\&caseSearchType=US_APPLICATION) or Trademark Search links with a ?query= (https://tmsearch.uspto.gov/search/search-results?query=coffee).

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

Only for 'expiring': first day of the deadline window, YYYY-MM-DD. Empty = today.

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

Only for 'expiring': last day of the window, YYYY-MM-DD (up to one year after the start). Empty = 30 days after the start.

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

USPTO's own live/dead flag. Empty = all.

## `registeredOnly` (type: `boolean`):

Keep only marks that reached registration (skips pending applications that were never registered).

## `internationalClasses` (type: `array`):

Keep marks in any of these classes, one per line (for example: 30, 43 or IC 030). Empty = all 45 classes.

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

Only applications filed on or after this date (2024-01-01, or just a year like 2024).

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

Only applications filed on or before this date (2024-12-31, or just a year like 2024).

## `exactPhrase` (type: `boolean`):

Match the mark text words in this exact order ("blue bottle" will not match "bottle of blue"). Off = all words in any order.

## `excludeIndividualOwners` (type: `boolean`):

Skip marks owned by individuals or sole proprietors, to get a list of companies only.

## `excludeKeywords` (type: `array`):

Words, one per line. Marks with any of them in the mark text are skipped and not charged.

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

Order of the results. Searches that ask for more than 10,000 marks are always read newest first (the USPTO index caps one query at 10,000, so the Actor splits it by filing date).

## `maxResultsPerSearch` (type: `integer`):

How many trademarks to take from each mark text, owner, goods search or link. Empty = 100. Up to 100,000: past 10,000 the Actor splits the search by filing year and month.

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

Hard cap on charged trademarks for the whole run, across all searches. Empty or 0 = no cap besides the per-search limit.

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

Apify datacenter proxy is the default and works for USPTO. Refused requests are retried on a fresh IP, then on a US residential IP.

## `monitorMode` (type: `boolean`):

Remembers every trademark this search returned (in a key-value store of your account named uspto-trademark-monitor) and, on the next runs, delivers only the new ones and the ones whose status changed (changeType: new or statusChanged, with previousStatus). Unchanged marks are not delivered and not charged. The newest filings are checked first; maxResultsPerSearch is how many of the newest are checked per search.

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

Names this watch so different searches keep separate memories (for example coffee-class-30). Empty = default.

## `alertOnStatusChange` (type: `boolean`):

On by default when monitoring: a mark already seen comes back when its USPTO status changes (for example published for opposition, registered, abandoned). Turn off to get only new marks.

## Actor input object example

```json
{
  "searchTerms": [
    "coffee"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "alertOnStatusChange": true
}
```

# Actor output Schema

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

No description

## `resultsCsv` (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 = {
    "searchTerms": [
        "coffee"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapewise/uspto-trademark-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 = {
    "searchTerms": ["coffee"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapewise/uspto-trademark-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 '{
  "searchTerms": [
    "coffee"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call scrapewise/uspto-trademark-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapewise/uspto-trademark-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/juVfbDk40uNbcYNQ5/builds/G4PXinejriyJ5mlLh/openapi.json
