# USPTO Trademark Data Scraper (`axiomworks/uspto-trademark-search-scraper`) Actor

Search the USPTO trademark service and return structured application and registration records, including mark text, serial number, owner, status, classes, goods and services, and dates.

- **URL**: https://apify.com/axiomworks/uspto-trademark-search-scraper.md
- **Developed by:** [Axiom Works](https://apify.com/axiomworks) (community)
- **Categories:** Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.98 / 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.
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

**Returns:** one row per trademark with markText, serialNumber, registrationNumber, ownerName, status, classes, filingDate, firstUseDate, goodsAndServices.
**Input:** `{"searchTerms": ["nike"], "status": "live", "internationalClasses": [25], "maxItems": 20}`
**Best for:** brand clearance checks, competitor trademark monitoring, attorney and owner lead lists.

```json
{"id": "99905286", "markText": "NIKE FREE IQ", "ownerName": "Nike, Inc. (CORPORATION; Oregon, USA)", "status": "NEW APPLICATION - RECORD INITIALIZED NOT ASSIGNED TO EXAMINER", "isLive": true, "classes": ["025"], "filingDate": "2026-06-25", "filingBasis": ["1b"]}
```

### What does USPTO Trademark Scraper do?

USPTO Trademark Scraper turns the public United States Patent and Trademark Office trademark search into structured data. You give it one or more mark texts, serial numbers, registration numbers or an owner name, optionally narrow the results by status, international class and dates, and it returns one clean record per trademark application or registration. Each record has the mark text, serial and registration number, owner, status, classes, goods and services, filing and registration dates and a link back to the USPTO case page.

The Actor reads the same JSON search service that the USPTO trademark search website uses in your browser. It does not log in, it does not need an API key and it does not solve CAPTCHAs. It works without a proxy, makes about one or two requests per second and retries politely if the service answers with a temporary error.

Typical uses include clearance searches before you file a new mark, monitoring what a competitor has filed, building a list of all live marks in a class, checking who owns a registration, and feeding trademark data into a spreadsheet, a database or an AI agent. The Actor is an independent tool and is not affiliated with or endorsed by the USPTO.

Because every search returns plain JSON, you can export the dataset as JSON, CSV, Excel, XML or HTML from the Apify Console, or fetch it through the API.

### What data can you get?

Every record contains the fields below. Fields that the USPTO does not publish for a given mark (for example the registration number of a pending application) are left out of that record instead of being filled with placeholders.

| Field | Type | Description |
|---|---|---|
| `id` | string | Stable unique id, equal to the serial number |
| `sourceUrl` | string | TSDR case status link for the application |
| `markText` | string | Wordmark text; empty for design-only marks |
| `serialNumber` | string | USPTO application serial number |
| `registrationNumber` | string | Registration number; empty for pending applications |
| `ownerName` | string | Owner name with entity type and state, as published |
| `ownerCity` | string | First published city when the USPTO lists multiple owner locations |
| `ownerState` | string | First published state, postal code and country when multiple locations appear |
| `attorney` | string | Attorney of record |
| `status` | string | USPTO status description, such as REGISTERED |
| `statusCode` | number | Numeric USPTO status code |
| `isLive` | boolean | True while the application or registration is live |
| `classes` | array of strings | International (Nice) classes, always three digits such as `025` |
| `goodsAndServices` | array of strings | Goods and services text, one entry per class |
| `filingDate` | string | Filing date as YYYY-MM-DD |
| `registrationDate` | string | Registration date as YYYY-MM-DD |
| `markType` | array of strings | Mark type labels such as TRADEMARK |
| `cancelDate` | string | Cancellation date when the mark was cancelled |
| `ownerEntityType` | string | Legal entity type of the owner |
| `ownerCitizenship` | string | State or country of the owner entity |
| `ownerAddress` | array of strings | Full owner text with role, entity and street address, as published |
| `firstUseDate` | string | Date of first use anywhere |
| `firstUseInCommerceDate` | string | Date of first use in commerce |
| `publicationDate` | string | Date published for opposition |
| `abandonDate` | string | Date the application was abandoned |
| `renewalDate` | string | Latest renewal date |
| `filingBasis` | array of strings | Current filing basis codes such as 1a (use) or 1b (intent to use) |
| `registrationType` | array of strings | Register type such as PRINCIPAL or SUPPLEMENTAL |
| `drawingType` | string | USPTO drawing code description |
| `disclaimer` | string | Disclaimer text of the mark |
| `designCodes` | array of strings | Individual design search codes of logo marks; comma-separated USPTO values are split into codes |
| `markDescription` | array of strings | Description of the mark drawing |
| `priorRegistrations` | array of strings | Prior registration numbers claimed |
| `proceedings` | array of strings | TTAB proceeding numbers (oppositions, cancellations) linked to the mark |
| `hasAssignmentRecorded` | boolean | True if an ownership assignment is recorded |
| `prosecutionHistory` | array | Only with the details option: dated events of the case file |
| `maintenance` | object | Only with the details option: renewal and maintenance information |
| `assignments` | object | Only with the details option: assignment records |

Older records in the USPTO database store classes in a slightly different way (for example `025.`) and dates with a time suffix. The Actor normalises both, so classes are always three-digit strings and dates are always plain dates.

#### What is new

Each record now also carries owner entity type, citizenship and full owner address, first-use dates, publication, abandon and renewal dates, filing basis, registration type, drawing type, disclaimer, design codes, mark description, prior registrations, linked TTAB proceeding numbers and an assignment-recorded flag. Owner entity type and citizenship use the first non-empty published value when the search index supplies multiple values, matching the selection used for owner city and state. Fields the USPTO leaves empty are omitted from the item.

### How to use USPTO Trademark Scraper

1. Open the Actor in the Apify Console and go to the Input tab.
2. Enter one or more mark texts, for example `nike`. A mark text is a phrase match, so `nike` also finds marks such as `NIKE FREE`.
3. Optionally set the status, one or more international classes, filing dates or registration dates.
4. Set the maximum number of items you want and press Start.
5. When the run finishes, open the Output tab to view or download the dataset.

You can also look up exact records. Put serial numbers into the serial numbers field or registration numbers into the registration numbers field. You can search by owner alone as well: leave the mark text empty and enter an owner name such as `Nike, Inc.`.

If you combine several mark texts, each one runs as its own search and the results are merged. A trademark that matches more than one search is returned only once.

#### Large searches

The USPTO search service returns at most 10,000 results for a single query. If a search matches more than that, the Actor logs a warning. To collect everything, split the search into smaller ones, for instance one run per international class or per range of filing dates.

#### Details option

When you switch on the details option, the Actor makes one extra request per record to the USPTO case status service. This adds the prosecution history, the maintenance information and the assignments to each record. Correspondent e-mail addresses that appear in the case file are removed from the output. Runs with details are slower because of the extra request, so use a smaller item limit.

### Input

| Field | Type | Description |
|---|---|---|
| `searchTerms` | array of strings | Mark texts to search, phrase match anywhere in the mark |
| `serialNumbers` | array of strings | Exact application serial numbers to look up |
| `registrationNumbers` | array of strings | Exact registration numbers to look up |
| `ownerName` | string | Only marks whose owner name contains this phrase |
| `status` | string | `all`, `live` or `dead`. Default `all` |
| `internationalClasses` | array of integers | Classes 1 to 45 that the mark must be filed in |
| `filedFrom`, `filedTo` | string | Filing date range, YYYY-MM-DD |
| `registeredFrom`, `registeredTo` | string | Registration date range, YYYY-MM-DD |
| `includeDetails` | boolean | Add prosecution history, maintenance and assignments. Default false |
| `maxItems` | integer | Total number of records to return, 1 to 10000. Default 50 |
| `proxyConfiguration` | object | Apify Proxy settings. Default is no proxy |

Example input:

```json
{
  "searchTerms": ["nike"],
  "status": "live",
  "internationalClasses": [25],
  "maxItems": 20
}
```

The Actor returns exactly the number of records you ask for in `maxItems` when that many exist, and never more. If the input is invalid, for example a date in the wrong format, the run fails within seconds with a clear message. If a search term matches nothing, the run finishes successfully with zero items and a status message that says what to change (shorter text, fewer filters, digits-only numbers). On a successful run with results the status message is `Done: <n> results.` followed by a rating request.

### Output

Each item in the dataset looks like this. The example is a real record returned by the Actor.

```json
{
  "id": "73361064",
  "sourceUrl": "https://tsdr.uspto.gov/#caseNumber=73361064&caseSearchType=US_APPLICATION&caseType=DEFAULT&searchType=statusSearch",
  "serialNumber": "73361064",
  "markText": "NIKE",
  "registrationNumber": "1237469",
  "ownerName": "Nike, Inc. (CORPORATION; OREGON, USA)",
  "ownerCity": "Beaverton",
  "ownerState": "OREGON 970056453, UNITED STATES",
  "attorney": "Jennifer Martin Reynolds",
  "status": "REGISTERED AND RENEWED",
  "statusCode": 800,
  "isLive": true,
  "classes": ["025"],
  "goodsAndServices": ["IC 025: ATHLETIC AND CASUAL CLOTHING FOR MEN, WOMEN AND CHILDREN-NAMELY, SHIRTS, PANTS, SHORTS, JACKETS, HEADWEAR, and SOCKS."],
  "filingDate": "1982-04-22",
  "registrationDate": "1983-05-10",
  "markType": ["TRADEMARK"]
}
```

Results are sorted by filing date, newest first. The dataset has an overview view in the Console that shows the most useful columns.

### How much does it cost?

The Actor is charged per result: you pay for each trademark record that is added to the dataset, and nothing for records that are not returned. See the Pricing tab of the Actor for the current rate. Because the USPTO service is free and needs no proxy, there are no other costs besides the usual Apify platform usage. Use `maxItems` to cap what a run can cost.

### Use with AI agents (MCP)

You can call this Actor from any AI agent that supports the Model Context Protocol through the Apify MCP server. Use this server URL:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com/?tools=axiomworks/uspto-trademark-search-scraper"
    }
  }
}
```

Example prompts for your agent:

- "Find all live trademarks for the mark NIKE in class 25 and list the owner and registration number."
- "Who owns the trademark with serial number 98029846, and what is its current status?"
- "List trademarks containing the word apple that were filed since 2022."

### Integrations and API

You can start the Actor from your own code with the Apify API clients or with a plain HTTP request. Replace `YOUR_API_TOKEN` with your token.

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")
run = client.actor("axiomworks/uspto-trademark-search-scraper").call(
    run_input={"searchTerms": ["nike"], "status": "live", "maxItems": 20}
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["markText"], item["serialNumber"], item["status"])
```

JavaScript:

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });
const run = await client.actor('axiomworks/uspto-trademark-search-scraper').call({
    searchTerms: ['nike'],
    status: 'live',
    maxItems: 20,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => process.stdout.write(`${item.markText} ${item.serialNumber}\n`));
```

cURL:

```bash
curl -X POST "https://api.apify.com/v2/acts/axiomworks~uspto-trademark-search-scraper/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"searchTerms": ["nike"], "status": "live", "maxItems": 20}'
```

You can also connect the dataset to Google Sheets, Make, Zapier, n8n or webhooks through the Apify integrations, and schedule the Actor to run daily to monitor new filings by an owner or in a class.

### FAQ

**Does it need a proxy?** No. The USPTO search works from normal data center addresses. The proxy setting is there in case the service starts blocking your traffic; if you enable it, blocked requests are retried on a fresh proxy session.

**Why is `registrationNumber` missing on some records?** Pending applications have not been registered yet, so the USPTO has no registration number for them.

**Why is `markText` missing on some records?** Design-only marks, such as a logo without words, have no wordmark text.

**Why do I get marks that only contain my search word?** Mark text search is a phrase match anywhere in the mark. A search for `apple` also returns marks such as `GREEN APPLE`. Filter the results by `markText` afterwards if you need exact matches.

**Why did I get fewer items than `maxItems`?** Fewer marks matched your search and filters. Check the log; it lists the number of matches.

**What does the class filter do when I list several classes?** Each class you list must be present on the mark.

**How fresh is the data?** The Actor reads the live USPTO search index, which is updated by the USPTO regularly. The data is as current as the USPTO website.

**What happens if the USPTO changes its service?** The search service is not an official documented API. If its format changes the Actor may need an update; please report problems through the Issues tab.

### Is it legal to scrape USPTO data?

The USPTO publishes trademark records as public information so that anyone can search them. The Actor only reads this public data without logging in and without bypassing any protection, and it keeps its request rate low so that it does not burden the service. The records include owner names, addresses and attorney names exactly as the USPTO publishes them. You are responsible for using the data in line with applicable laws, such as privacy and marketing rules, and with the terms of the source. A trademark search is not legal advice and does not replace a professional clearance search.

### Feedback

If something does not work, or you need another field, open an issue on the Actor page in the Apify Store. Please include the run link and the input you used so we can reproduce the problem.

# Actor input Schema

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

List of trademark wordmarks; each is a phrase match anywhere in the mark and runs as its own search, e.g. \["nike", "just do it"]. To look up only by serial/registration number or owner, omit this and fill those fields instead. Matches are US trademarks only.

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

Exact USPTO application serial numbers, digits only, e.g. \["98029846"]. Non-digits are stripped. Returns those applications; combine with status/class filters if needed. Default \[].

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

Exact USPTO registration numbers, digits only, e.g. \["7401694"]. Returns those registered marks. Default \[].

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

Owner/applicant name phrase, e.g. "Nike, Inc.". Works alone (all marks of that owner) or narrows the other searches. Leave empty for no owner filter.

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

One of "all" (default), "live" (registered or pending) or "dead" (abandoned, cancelled, expired). Example: "live".

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

Integers 1-45 that the mark must be filed in, e.g. \[25] for clothing or \[9, 42] for software (all listed classes must match). Default \[] means any class.

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

Earliest filing date as YYYY-MM-DD, e.g. "2020-01-01". Empty means no lower bound.

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

Latest filing date as YYYY-MM-DD, e.g. "2024-12-31". Empty means no upper bound.

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

Earliest registration date as YYYY-MM-DD, e.g. "2020-01-01". Empty means no lower bound; unregistered applications are excluded when set.

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

Latest registration date as YYYY-MM-DD, e.g. "2024-12-31". Empty means no upper bound; unregistered applications are excluded when set.

## `includeDetails` (type: `boolean`):

true adds prosecutionHistory, maintenance and assignments to each record via one extra request per record (slower; use a small maxItems). Default false.

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

Maximum trademark records returned in total across all searches, 1-10000, default 50. Use a small number (5-20) to preview. USPTO caps one search at 10000 results; narrow by class or dates beyond that.

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

Apify Proxy settings, e.g. {"useApifyProxy": true}. Default is no proxy, which works for the USPTO; enable only if requests get blocked (403/429).

## Actor input object example

```json
{
  "searchTerms": [
    "nike"
  ],
  "serialNumbers": [],
  "registrationNumbers": [],
  "status": "live",
  "internationalClasses": [
    25
  ],
  "includeDetails": false,
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Structured trademark records

# 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": [
        "nike"
    ],
    "status": "live",
    "internationalClasses": [
        25
    ],
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("axiomworks/uspto-trademark-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 = {
    "searchTerms": ["nike"],
    "status": "live",
    "internationalClasses": [25],
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("axiomworks/uspto-trademark-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 '{
  "searchTerms": [
    "nike"
  ],
  "status": "live",
  "internationalClasses": [
    25
  ],
  "maxItems": 20
}' |
apify call axiomworks/uspto-trademark-search-scraper --silent --output-dataset

```

## MCP server setup

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