# USPTO Trademark Scraper - Marks, Owners, Status & New Filings (`rjmacarthy/uspto-trademark-scraper`) Actor

Search the US trademark register (USPTO) by word mark, owner, Nice class or serial number. Get status, filing and registration dates, owner, classes and goods/services, plus an "only new" watch mode for new filings. No login.

- **URL**: https://apify.com/rjmacarthy/uspto-trademark-scraper.md
- **Developed by:** [rj](https://apify.com/rjmacarthy) (community)
- **Categories:** Automation, Developer tools
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 trademark records

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

## USPTO Trademark Scraper: Search US Trademarks, Owners, Status & New Filings

Search the **US trademark register (USPTO)** by word mark, owner, Nice class or serial number and get clean, structured trademark records: status, filing / registration / opposition dates, owner and jurisdiction, Nice classes, goods and services, filing basis and the mark image. Turn on **"Only new trademarks"** and schedule it, and you have a cheap **trademark watch** that sends you only new filings that match your brand, competitor or class. It uses the same public JSON API as the official USPTO Trademark Search, so it needs no login, no browser and no proxy. Unlike most trademark Actors, one run handles keyword, owner, class and serial-number searches together, and the price stays at **$0.005 per trademark**.

### What data can you get?

| Field | Example | Notes |
|---|---|---|
| `markText` | `COCA-COLA` | Word mark |
| `serialNumber`, `registrationNumber` | `78264035`, `2844970` | Registration number is null while pending |
| `status`, `statusCategory` | `live`, `Registered` | Registered / Pending / Abandoned / Cancelled / Dead |
| `statusDescription`, `statusDate` | `The registration has been renewed.`, `2024-08-23` | Exact TSDR status text and date with **Fetch exact TSDR status** |
| `filingDate`, `registrationDate` | `2003-06-18`, `2004-05-25` | ISO dates |
| `publishedForOppositionDate` | `2004-03-02` | When the 30-day opposition window opened |
| `abandonmentDate`, `cancellationDate` | `2009-06-01` | For dead marks |
| `ownerName`, `ownerType` | `The Coca-Cola Company`, `CORPORATION` | Current owner as recorded on the register |
| `ownerState`, `ownerCountry` | `DELAWARE`, `USA` | Jurisdiction only, never a street address |
| `niceClasses` | `[28]` | International (Nice) classes 1-45 |
| `goodsAndServices` | `IC 028: Board games; ...` | One line per class, max 2,000 characters |
| `markType`, `markCategory` | `Standard characters`, `TRADEMARK` | Drawing type and mark category |
| `filingBasis`, `register` | `1(a)`, `PRINCIPAL` | 1(a) use, 1(b) intent to use, 44(e), 66(a) |
| `drawingUrl` | `https://tmcms-docs.uspto.gov/cases/78264035/mark/large.png` | Image of the mark |
| `url` | TSDR status page | Link to the official record |
| `searchType`, `searchTerm`, `scrapedAt` | `keyword`, `coca-cola` | Which search found the mark |

### Use cases

- **Trademark watch for law firms and brand owners:** schedule a daily or weekly run that outputs only new applications containing your client's mark or filed in their classes, then oppose before the deadline.
- **Name clearance:** check whether a product, app or startup name is already taken in the classes you care about, live and dead.
- **Competitor intelligence:** list every mark a competitor owns or has just filed (new filings often reveal product launches months early).
- **Ecommerce sellers:** check brand names before listing on Amazon or Shopify to avoid IP complaints.
- **Portfolio audits:** pull status, dates and classes for a list of serial numbers in one run.
- **Market research:** count and analyse new filings per class (e.g. all clothing marks filed this week).

### How to use

1. Enter one or more **Search terms** (word marks), **Owner names** or **Serial numbers**. Each is its own search.
2. Optionally narrow by **Nice classes**, **Status** (live / dead / all) and **Filed within (days)**.
3. Click **Start**. Results appear in the dataset; download them as JSON, CSV or Excel, or read them through the API.

**Check if a name is taken in a class (live and dead marks):**

```json
{
    "searchTerms": ["bloom"],
    "classes": ["3"],
    "status": "all",
    "maxItems": 20
}
```

**All live trademarks of a company:**

```json
{
    "ownerNames": ["Patagonia, Inc."],
    "status": "live",
    "maxItems": 25
}
```

**New clothing trademark filings of the last 7 days (no search term needed):**

```json
{
    "classes": ["25"],
    "filedWithinDays": 7,
    "sortBy": "newest",
    "maxItems": 20
}
```

**Weekly watch: new "cola" filings in soft drinks, only marks not seen before:**

```json
{
    "searchTerms": ["cola"],
    "classes": ["32"],
    "filedWithinDays": 14,
    "sortBy": "newest",
    "onlyNew": true,
    "watchName": "cola-watch"
}
```

**Look up serial numbers with the exact TSDR status:**

```json
{
    "serialNumbers": ["78264035", "99485163"],
    "fetchDetails": true
}
```

### Output example

Real item from a run (search `bloom`, class 3, all statuses):

```json
{
    "id": "86183032",
    "serialNumber": "86183032",
    "registrationNumber": "5291299",
    "url": "https://tsdr.uspto.gov/#caseNumber=86183032&caseType=SERIAL_NO&searchType=statusSearch",
    "markText": "EVER BLOOM",
    "markType": "Standard characters",
    "markCategory": "TRADEMARK",
    "drawingUrl": "https://tmcms-docs.uspto.gov/cases/86183032/mark/large.png",
    "status": "dead",
    "statusCategory": "Cancelled",
    "statusDescription": "Cancelled",
    "statusDate": null,
    "filingDate": "2014-02-03",
    "registrationDate": "2017-09-19",
    "publishedForOppositionDate": "2014-06-17",
    "abandonmentDate": null,
    "cancellationDate": "2024-03-29",
    "ownerName": "SHISEIDO COMPANY, LIMITED",
    "ownerType": "CORPORATION",
    "ownerState": null,
    "ownerCountry": "JAPAN",
    "ownerRole": "ORIGINAL REGISTRANT",
    "niceClasses": [3],
    "goodsAndServices": "(CANCELLED) IC 003: [ Cosmetic creams for skin care; cosmetic preparations for skin care; lotions for skin; ... ].",
    "filingBasis": "1(a)",
    "register": "PRINCIPAL",
    "detailsFetched": false,
    "searchType": "keyword",
    "searchTerm": "bloom",
    "scrapedAt": "2026-11-08T12:28:52.914Z"
}
```

With **Fetch exact TSDR status** on, `statusDescription` holds the official status text (e.g. `The registration has been renewed.`), `statusDate` is filled and `detailsFetched` is `true`.

A `RUN_SUMMARY` record in the key-value store lists, per search, the total number of matches, how many marks were output, any serial numbers that were not found, and request statistics.

### Pricing

Pay per event: you pay only for results, not for run time.

| Event | Price | When |
|---|---|---|
| `trademark` | $0.005 | Each trademark record in the output |
| `trademark-details` | $0.002 | Each mark for which the exact TSDR status was fetched (only with **Fetch exact TSDR status**) |

Examples:

- 1,000 trademarks ≈ **$5.00**
- 1,000 trademarks with exact TSDR status ≈ $5.00 + $2.00 = **$7.00**
- A daily watch that finds 5 new filings a day ≈ $0.025 per day, about **$0.75 per month**

Set **Maximum cost per run** in the run options; the Actor stops cleanly when the budget is reached and never charges beyond it.

### Tips and limits

- **Watch mode:** "Only new trademarks" remembers the serial numbers each watch has output (in a named key-value store, per **Watch name**). The first run outputs and charges everything it finds, so combine it with **Filed within (days)** and **Sort by: Newest filings first**. Use a separate watch name per client or brand.
- **Search terms** match marks that contain the words (phrase match plus the USPTO's pseudo-mark spellings). For a fuzzy "sounds like" clearance search, run several spellings.
- **Owner search** matches the owner name as a phrase (small word-order differences allowed), so "Patagonia" also finds "Eko Patagonia". Use the full legal name for precision.
- **Serial-number lookups** ignore the status, class and date filters. Serial numbers that don't exist are listed in `RUN_SUMMARY`.
- **10,000 results per search:** the USPTO search returns at most 10,000 results for one query. Narrow big searches by class, status or filing date.
- **statusDate** is only filled with **Fetch exact TSDR status**, which makes one extra request per mark (about one mark per second, following the USPTO's rate guidance).
- **Data freshness:** the USPTO index is usually updated daily; brand-new filings appear a day or so after filing.
- Only US (USPTO) trademarks. EUIPO / WIPO / TMview are not covered.

### FAQ

**Is it legal to scrape USPTO trademark data?**
Trademark records are public government records, published by the USPTO for anyone to search. This Actor reads only that public data, at a polite rate, without logging in. It does not collect personal contact data: no emails, phone numbers, street addresses or attorney/correspondent contacts. Owner names are kept because they are the public register owner, but only the owner's state and country are returned. You are responsible for using the data in line with the law and the USPTO terms of use.

**Do I need a proxy?**
No. The USPTO search API answers Apify's servers directly. If you ever see "HTTP 403/429" or "AWS WAF challenge" in the log, enable Apify Proxy (datacenter). Residential proxies are not supported: if you pick a residential group, the Actor logs a warning and uses datacenter proxy instead.

**Why is `statusDate` empty?**
The search index doesn't include the date of the latest status. Turn on **Fetch exact TSDR status** to get it with the exact status text.

**How fresh is the data?**
Live: every run queries the USPTO trademark search at run time.

**Can I search by mark image / design code?**
Not in this version. Ask in the Issues tab if you need it.

### Integrations

- **API:** run the Actor and read results with the Apify API or the JavaScript / Python clients.
- **Make, Zapier, n8n:** use the Apify integration to send new filings from a scheduled watch to Slack, email, Google Sheets or your CRM.
- **MCP:** AI agents can call this Actor through the Apify MCP server to check trademark availability on demand.
- **Webhooks:** trigger your own endpoint when a watch run finishes.

### Changelog

- **0.1** (November 2026): first release. Keyword, owner, serial-number and class/date searches, live/dead status filter, exact TSDR status, only-new watch mode.

### More scrapers by the same developer

- [AI Visibility Tracker: ChatGPT, Perplexity, Gemini, Claude](https://apify.com/rjmacarthy/ai-search-visibility-tracker)
- [AliExpress Scraper - Product Search, Prices, Ratings & Details](https://apify.com/rjmacarthy/aliexpress-scraper)
- [Apple App Store Scraper: Apps, Search & Reviews](https://apify.com/rjmacarthy/app-store-scraper)
- [AutoScout24 Scraper - Used Car Listings & Prices (Europe)](https://apify.com/rjmacarthy/autoscout24-scraper)
- [Bilibili Scraper - Videos, Search, Popular & Uploader Stats](https://apify.com/rjmacarthy/bilibili-scraper)
- [Bing Search Scraper: Organic Results, Ads & Related Searches](https://apify.com/rjmacarthy/bing-search-scraper)

Browse all my Actors on [my Apify Store profile](https://apify.com/rjmacarthy).

### Support

Found a bug or need a field that's missing? Open an issue in the Issues tab and include your input and the run ID.

# Actor input Schema

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

Word marks to search for, e.g. "coca-cola" or "air jordan". Each term is a separate search that finds marks containing the words (also via the USPTO's pseudo-mark spellings, e.g. "4EVER" for "forever").

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

Find the marks of a company (current or original owner), e.g. "Patagonia, Inc.". Matching is by phrase and also catches small variations in word order.

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

Look up trademarks directly by their 8-digit USPTO serial (application) number, e.g. 97123456. Status, class and date filters do not apply to these lookups.

## `classes` (type: `array`):

Only marks registered/applied for in at least one of these international (Nice) classes, 1-45. E.g. 25 = clothing, 9 = software and electronics, 32 = soft drinks, 35 = retail and advertising.

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

Live marks (registered or pending), dead marks (abandoned, cancelled or expired) or both.

## `filedWithinDays` (type: `integer`):

Only applications filed in the last N days. Combine with "Only new trademarks" for a scheduled trademark watch. If you leave all searches empty, this lists ALL recent filings (optionally limited by Nice classes).

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

Best match first, or newest filings first (recommended for watches and recent-filing searches).

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

Maximum number of trademarks to output for each search term / owner. 0 = no limit (the USPTO search returns at most 10,000 per search).

## `fetchDetails` (type: `boolean`):

Make one extra request per mark to get the exact USPTO (TSDR) status text and status date, e.g. "Notice of allowance issued" or "Published for opposition". Without it, statusDescription is a category (Registered / Pending / Abandoned / Cancelled) and statusDate is empty. Charged as a separate event and slower (about 1 mark per second).

## `onlyNew` (type: `boolean`):

Output only trademarks that this watch has not output before (remembered by serial number across runs). Schedule the Actor to get a new-filings alert feed. The first run outputs (and charges) everything it finds, so pair it with "Filed within (days)".

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

Name of the watch for "Only new trademarks". Use a different name for each independent watch (e.g. one per client).

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

Not needed normally. Enable Apify Proxy (datacenter) only if the USPTO blocks requests from Apify's servers. Residential proxies are not supported and fall back to datacenter.

## Actor input object example

```json
{
  "searchTerms": [
    "coca-cola"
  ],
  "status": "live",
  "sortBy": "relevance",
  "maxItems": 15,
  "fetchDetails": false,
  "onlyNew": false,
  "watchName": "default",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Mark, status, filing/registration dates, owner, Nice classes and TSDR link.

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

Every field per trademark, including goods and services, filing basis and owner jurisdiction.

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

Per-search counts, serial numbers not found, request statistics and warnings.

# 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": [
        "coca-cola"
    ],
    "status": "live",
    "maxItems": 15
};

// Run the Actor and wait for it to finish
const run = await client.actor("rjmacarthy/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": ["coca-cola"],
    "status": "live",
    "maxItems": 15,
}

# Run the Actor and wait for it to finish
run = client.actor("rjmacarthy/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": [
    "coca-cola"
  ],
  "status": "live",
  "maxItems": 15
}' |
apify call rjmacarthy/uspto-trademark-scraper --silent --output-dataset

```

## MCP server setup

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