# Trademark Search API & Watch: USPTO + Australia (`data-done-right/trademark-search`) Actor

Trademark search: check whether a brand name is already registered. Search by word mark, owner or Nice class in the US (USPTO) and Australia, with exact, fuzzy and sound-alike flags, plus trademark watch for new filings. Pay per row; no API key for Australia.

- **URL**: https://apify.com/data-done-right/trademark-search.md
- **Developed by:** [Data Done Right](https://apify.com/data-done-right) (community)
- **Stats:** 2 total users, 1 monthly users, 80.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

## Trademark Search API & Watch: USPTO + Australia

**Trademark search** and **trademark watch** without writing code. Search trademarks by word mark (exact, contains or fuzzy and sound-alike), owner, Nice class or number, and get clean rows: mark text, serial and registration number, live/dead status, filing and registration dates, owner name and address, Nice classes, goods and services, attorney, mark image link and the official record link. Watch mode reports **only new filings** that look like your brand since the last run, for brand protection alerts.

Two offices, official sources only:

| Office | Source | Key | What you can do |
|---|---|---|---|
| **Australia (AU)** | IP Australia **IP RAPID** open data on data.gov.au (refreshed weekly, CC BY 4.0) | **none** | Search the **whole Australian register** by word mark, owner and Nice class; lookup by number; weekly watch |
| **United States (US)** | USPTO **TSDR API** (case status) and USPTO **Open Data Portal** (daily trademark application files) | free USPTO keys | Lookup by serial or registration number; search and watch **new US filings** by word mark, owner and Nice class |

No scraping, no logins, no browser automation: only the documented APIs and open data the offices publish.

### How to search trademarks

1. Pick the **Trademark office** (AU needs nothing; US needs a free key, see below).
2. Pick **What do you want?**: *Search*, *Lookup* or *Watch*.
3. Enter **Word marks** (one per line) and choose the **Match type**:
   - `exact`: same text (case, accents, punctuation and spacing ignored)
   - `contains`: the term appears inside the mark (`kombucha` finds `KOMBUCHA KING`)
   - `fuzzy`: also close spellings and sound-alikes (`kombucha` finds `KOMBUCHER`, `COMBUCHA`)
4. Optional filters: **Owner names**, **Nice classes**, **Live marks only**, filing date range. Set **Max results** to cap rows and cost.

Every row says how it matched: `matchType` (exact, contains, fuzzy, phonetic), `exactMatch`, `containsMatch`, `fuzzyMatch`, `phoneticMatch` and a `similarity` score from 0 to 1. Best matches come first: exact, then contains, then fuzzy; live before dead; newest first.

### How trademark watch works

Choose **Watch** and schedule the Actor (daily for US, weekly for AU). Each run remembers what it already reported, so you only get **new** matching filings:

- **US**: each run reads the USPTO daily application files it has not processed yet (weekends and missed days are caught up automatically, up to 90 days). The first run looks back **daysBack** days.
- **AU**: IP Australia refreshes IP RAPID weekly. A run on an unchanged snapshot reports nothing and says so; otherwise it reports matching marks filed recently that were not reported before.

Send the matches to Slack, email or a database with an integration (see Related tools).

### Trademark lookup by serial number (USPTO and Australia)

Choose **Lookup**. US: put 8-digit **serial numbers** or 7-digit **registration numbers** (needs the TSDR key). AU: put trade mark numbers in **Serial / trade mark numbers** (no key).

### Get your free USPTO API keys (US only)

The USPTO runs two separate key systems:

- **TSDR API key** (US lookup by number): sign in or create a free USPTO.gov account at [account.uspto.gov/api-manager](https://account.uspto.gov/api-manager/) and request a TSDR API key. Paste it into **USPTO TSDR API key**.
- **Open Data Portal key** (US search and watch): create a USPTO.gov account, verify your identity with ID.me, then get the key at [data.uspto.gov/apikey](https://data.uspto.gov/apikey). Paste it into **USPTO Open Data Portal API key**.

Both are free and stored as secrets; they are never logged or written to the dataset. If you only have one key, put it in either field and the Actor tries it for both. TSDR is rate limited per key: the Actor waits about 1 second between lookups and backs off when TSDR answers HTTP 429. Unused Open Data Portal keys are deleted after 90 days of inactivity; a scheduled watch keeps yours in use.

### What data can you extract

Same flat fields for both offices (empty when an office does not publish the value):
`office, markText, markImageWords, markImageDescription, markKind, serialNumber, registrationNumber, status (live/dead/unknown), statusCode, statusText, statusDate, filingDate, registrationDate, publishedForOppositionDate, deadDate, ownerName, ownerAddress, ownerCity, ownerState, ownerPostcode, ownerCountry, ownerEntityType, owners, niceClasses, goodsServices, goodsServicesText, attorney, attorneyFirm, match fields, markImageUrl, sourceUrl, source, license, dataAsOf`.

### Input example

```json
{
  "office": "US",
  "mode": "watch",
  "searchTerms": ["kombucha", "brewlabs"],
  "matchType": "fuzzy",
  "niceClasses": ["32"],
  "daysBack": 7,
  "odpApiKey": "YOUR_ODP_KEY"
}
```

Australian register search, no key:

```json
{
  "office": "AU",
  "mode": "search",
  "searchTerms": ["qantas"],
  "matchType": "fuzzy",
  "liveOnly": true,
  "maxResults": 50
}
```

### Output example

```json
{
  "recordType": "trademark", "office": "AU", "markText": "QANTAS", "markKind": "word",
  "serialNumber": "1771259", "registrationNumber": "1771259",
  "status": "live", "statusCode": "protected", "statusText": "Protected",
  "filingDate": "2016-05-17", "registrationDate": "2017-03-14",
  "ownerName": "qantas airways limited", "ownerAddress": "NSW, 2020, AU", "ownerCountry": "AU", "ownerAbn": "16009661901",
  "niceClasses": ["006", "009", "014", "016", "018"],
  "attorney": "herbert smith freehills kramer",
  "matchedTerm": "qantas", "matchType": "exact", "exactMatch": true, "containsMatch": true,
  "fuzzyMatch": true, "phoneticMatch": true, "similarity": 1.0,
  "sourceUrl": "https://search.ipaustralia.gov.au/trademarks/search/view/1771259",
  "source": "IP Australia IP RAPID open data (CC BY 4.0)", "dataAsOf": "2026-10-19"
}
```

A US row also has `goodsServices` (`[{"class": "009", "text": "Downloadable game software; ..."}]`), `ownerEntityType`, `attorneyFirm`, `markImageUrl` (`https://tsdr.uspto.gov/img/<serial>/large`) and a TSDR `sourceUrl`. Watch rows have `recordType: "watchMatch"`. A `SUMMARY` record and, when something needs your attention, a `NOTES` record are saved in the key-value store.

### Trademark search API

Call this Actor from the Apify API, Python, JavaScript, Make, Zapier or n8n and get trademark records as JSON, or export them to CSV, Excel or Google Sheets. You get one flat schema for the USPTO and IP Australia.

### Use it in Claude, ChatGPT and Cursor

Connect Apify's MCP server (mcp.apify.com) and your AI assistant can check names itself. For example: "is 'kombucha' already a registered trade mark in Australia in class 32?" The Australian office needs no key, so it works straight away.

### Use cases

- **Brand protection**: daily alerts for new US filings that copy or sound like your brand, filtered to your Nice classes.
- **Trademark clearance (Australia)**: check a name against the full Australian register, including dead marks.
- **Portfolio monitoring**: status, owner and dates for a list of US serial or registration numbers.
- **Lead generation for IP firms**: new filings by class, with the filer and attorney.

### How much does it cost

Pay per event:

- `trademark-record`: each trademark row you get.
- `watch-match`: each new match in watch mode (instead of `trademark-record`).
- `data-scan`: $0.01 for each pass over a data source, because the whole source is read whatever the number of results. An Australian run makes 1 to 3 passes (the register search, plus one for Nice classes and one for owners if you switch them on); a US search or watch makes one per USPTO daily file. US lookups by number have no scan fee.

Set **Max results** to cap the cost; if your spending limit is reached, the run stops cleanly and says so.

### Limits (honest)

- **USPTO has no official API to search the whole US register by word mark or owner.** US search and watch cover the **daily filing files** of the chosen window (new applications, or also changed cases). For a full US clearance search use the USPTO's own search system or a lawyer.
- US records from the daily files are as filed that day; use Lookup (TSDR) for the current status of a mark.
- AU data is IP Australia's **weekly** snapshot, so the newest filings can be up to a week behind. It has no goods/services text (classes only) and no street address, and names of **individual** owners are withheld (`ownerNameWithheld: true`).
- Each AU run streams large open-data files (about 200 MB for a search without owners and classes, about 800 MB with both), so an AU run takes roughly 30 seconds to 3 minutes whatever the number of results.
- Fuzzy matching is simple (edit distance and Soundex, mostly same first letter). It is a screening aid, not a legal likelihood-of-confusion opinion.
- US status lookups were tested on a real TSDR sample response. The daily-file parser follows the USPTO's published XML documentation and was tested on a sample built from that documentation; no live daily file has been parsed yet (that needs a key). If a field comes out empty on your first US run, tell us.

### FAQ

#### Is trademark search free?

The offices' data and keys are free. This Actor charges per result row on Apify; the Australian search needs no key at all.

#### Can I search the whole USPTO database by word mark?

Not through an official API: the USPTO only offers lookup by number (TSDR) and bulk files. This Actor searches the daily US filing files (new filings, ideal for watching) and looks up any mark by number.

#### How do I look up a trademark in Australia?

Choose the **AU** office and **Search**, then enter the name. You get every matching mark on the full Australian register, live and dead, with owner, classes and status. No key is needed.

#### Is there a USPTO trademark search API?

The USPTO offers lookup by number (TSDR) and daily bulk filing files, but no API that searches the whole register by name. This Actor uses both: lookup by serial or registration number, and search or watch over the daily filing files.

#### How do I get a USPTO API key?

See "Get your free USPTO API keys" above: a TSDR key from account.uspto.gov/api-manager for lookups, and an Open Data Portal key from data.uspto.gov/apikey (ID.me verification) for search and watch.

#### What is a Nice class?

The international classification of goods and services (classes 1 to 45, e.g. 9 software, 25 clothing, 32 non-alcoholic drinks). Filter by the classes your brand uses to cut noise.

#### How do I monitor new trademark filings for my brand?

Use Watch mode with your brand terms and fuzzy matching, add your Nice classes, and schedule it daily. You get only filings not reported before.

#### Is it legal to use this trademark data?

Trademark registers are public records. Australian data is IP Australia open data under CC BY 4.0 (keep the attribution in the `source` field). Owner names and addresses are published by the offices; use them in line with privacy and marketing laws where you are.

### Related tools

- **Companies House API: UK Company, Officer & PSC Data**: check the company behind a mark.
- **Company Enrichment API: Domain to Tech, Jobs & Socials**: website, socials and tech stack of an applicant.
- **Send Data to Slack, Discord, Email, Notion & Postgres**: deliver watch matches where your team works.

# Actor input Schema

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

AU = Australian register from IP Australia open data (no key needed, refreshed weekly). US = USPTO through its official APIs (needs a free USPTO key, see below).

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

Search marks by word mark, owner and Nice class; look up marks by number; or watch: report only NEW filings that match your brand terms since the last run (schedule it daily or weekly).

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

Brand names or words to search for, one per line. Matching ignores case, accents, punctuation and spacing.

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

exact = same text; contains = the term appears inside the mark; fuzzy = also close spellings (small edit distance) and sound-alikes (Soundex). Every row says which kind of match it is.

## `fuzzySimilarity` (type: `integer`):

For fuzzy: how close a spelling must be. 80 allows about 1 edit per 5 letters. Lower finds more look-alikes and more noise.

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

Owner (applicant/registrant) name contains this text, e.g. 'qantas airways'. Alone it searches by owner; with word marks it filters the results.

## `niceClasses` (type: `array`):

Only marks in any of these Nice classes, e.g. 9, 25, 35. Empty means all classes.

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

Lookup mode. US: 8-digit serial numbers (e.g. 97123456). AU: trade mark numbers (e.g. 1771259).

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

Lookup mode, US only: 7-digit registration numbers (e.g. 4567890).

## `liveOnly` (type: `boolean`):

Skip dead marks (abandoned, cancelled, expired, lapsed, refused).

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

Only marks filed on or after this date (YYYY-MM-DD).

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

Only marks filed on or before this date (YYYY-MM-DD).

## `daysBack` (type: `integer`):

US search and the first US watch run scan the USPTO daily application files of the last N days (later watch runs continue where the last run stopped, up to 90 days). The first AU watch run reports marks filed in the last N days (at least 7). Max 90.

## `newFilingsOnly` (type: `boolean`):

On: only cases newly filed in the scanned days. Off: also existing cases that changed (status updates, publication, registration).

## `includeClasses` (type: `boolean`):

Adds the Nice classes of each Australian mark (one more pass over the open data, about 10-30 s).

## `includeOwners` (type: `boolean`):

Adds owner name, state, postcode, country, ABN and agent (one more pass, about 30-60 s). Names of individual owners are withheld in the open data.

## `maxResults` (type: `integer`):

Caps the rows returned (and so the cost). Best matches first: exact, then contains, then fuzzy; live before dead; newest first.

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

Optional label for the watch memory. Runs with the same name share what was already reported. Empty = derived from the office, terms and filters.

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

US lookup by number. Free: sign in at account.uspto.gov/api-manager and request a TSDR key. Stored as a secret, never logged.

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

US search and watch (daily filing files). Free: USPTO.gov account verified with ID.me, then data.uspto.gov/apikey. Stored as a secret, never logged.

## Actor input object example

```json
{
  "office": "AU",
  "mode": "search",
  "searchTerms": [
    "kombucha"
  ],
  "matchType": "contains",
  "fuzzySimilarity": 80,
  "liveOnly": false,
  "daysBack": 7,
  "newFilingsOnly": true,
  "includeClasses": true,
  "includeOwners": true,
  "maxResults": 3
}
```

# Actor output Schema

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

All result items of this run (the default dataset), as JSON, CSV, Excel and more.

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

Key-value store records: the run summary, notes on any problems, and any files.

# 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 = {
    "office": "AU",
    "mode": "search",
    "searchTerms": [
        "kombucha"
    ],
    "matchType": "contains",
    "includeClasses": false,
    "includeOwners": false,
    "maxResults": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("data-done-right/trademark-search").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 = {
    "office": "AU",
    "mode": "search",
    "searchTerms": ["kombucha"],
    "matchType": "contains",
    "includeClasses": False,
    "includeOwners": False,
    "maxResults": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("data-done-right/trademark-search").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 '{
  "office": "AU",
  "mode": "search",
  "searchTerms": [
    "kombucha"
  ],
  "matchType": "contains",
  "includeClasses": false,
  "includeOwners": false,
  "maxResults": 3
}' |
apify call data-done-right/trademark-search --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,data-done-right/trademark-search"
        }
    }
}
```

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/7Ow3PGw0bUVdt4NuA/builds/dWEMLpfSLq1rfO5xJ/openapi.json
