# Trademark Search Scraper (`scrapyx/trademark-search-scraper`) Actor

Search 141M+ trademarks from 70+ registers worldwide (EUIPO, WIPO, USPTO, CNIPA, JPO, UKIPO and more) in one query. Filter by office, Nice class, status and mark type. Returns owner, filing and registration numbers, dates, classes and mark images. No API key.

- **URL**: https://apify.com/scrapyx/trademark-search-scraper.md
- **Developed by:** [Ibnu Adzim](https://apify.com/scrapyx) (community)
- **Categories:** Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.84 / 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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Trademark Search Scraper — TMview, 70+ Offices

Search **141 million+ trademarks** from more than 70 registers worldwide in a
single query — EUIPO, WIPO, USPTO, CNIPA (China), JPO (Japan), UKIPO, DPMA
(Germany), INPI, IP Australia and dozens more.

**No API key, no login, no account.**

### Why use this actor

- **One search, every register.** Instead of checking the EU, US, UK and
  Chinese offices separately, ask once and get all of them with a consistent
  row shape.
- **Covers USPTO without a key.** The USPTO's own TSDR API now requires
  registration ("Beginning October 2, you'll need to register for an API
  key…"). This route returns US marks anyway, alongside 70 other registers.
- **Real clearance filters.** Restrict by office, Nice class (1–45), status and
  mark type — all verified to genuinely narrow results, not silently ignored.
- **Owner names, numbers and dates.** Applicant, application and registration
  numbers, filing/registration/expiry dates, Nice classes, protected
  territories, and mark images where the office publishes one.
- **Honest counts.** Every search writes a summary row with the register's own
  match count next to how many rows the run could actually reach.

### Typical uses

- **Brand clearance** — is this name already registered in my classes and markets?
- **Trademark watch** — monitor new filings that resemble your brand.
- **Competitor tracking** — what is a company filing, where, and in which classes?
- **Portfolio audit** — list every mark an owner holds across jurisdictions.

### The one limit you need to know

**TMview serves at most 10,000 rows per query**, however many it reports as
matching. A search for `apple` reports 33,895 matches; you can retrieve 10,000
of them.

That ceiling is upstream — two limits apply at once (max page 200, max offset
10,000) and no tool can exceed them. This actor always fetches 100 rows per
request, which is the **only** setting that reaches the full window: at 20 rows
per request the page limit binds first and you would silently top out at 4,000.

**To go wider, split the search.** Each combination is its own 10,000-row window:

```json
{ "searchTerms": ["apple"], "offices": ["US"], "niceClasses": [9] }
{ "searchTerms": ["apple"], "offices": ["US"], "niceClasses": [25] }
{ "searchTerms": ["apple"], "offices": ["EM"] }
```

The summary row tells you when this applies (`upstream_total_exceeds_window`).

### Input

```json
{
  "searchTerms": ["apple", "tesla"],
  "searchCriteria": "C",
  "offices": ["EM", "US"],
  "niceClasses": [9],
  "statuses": ["Registered"],
  "maxItems": 100
}
```

| Field | Type | Description |
|---|---|---|
| `searchTerms` | array | **Required.** One brand name or word per entry. |
| `searchCriteria` | string | `C` contains, `E` exact, `B` begins with, `W` word match, `F` fuzzy/phonetic. |
| `offices` | array | Two-letter office codes (`EM` EU, `WO` WIPO, `US`, `GB`, `DE`, `CN`, `JP`…). Empty = all. |
| `niceClasses` | array | Nice classes 1–45 (`9` software, `25` clothing, `35` business, `42` IT services). |
| `statuses` | array | `Registered`, `Filed`, `Expired`, `Ended`, `Withdrawn`, `Refused`, `Opposed`. |
| `markTypes` | array | `Word`, `Figurative`, `Combined`, `3-D`, `Sound`, `Colour`… |
| `goodsServices` | array | Free-text terms matched against goods & services. |
| `maxItems` | integer | Results per term, up to the 10,000 upstream ceiling. |
| `maxConcurrency` | integer | Requests in flight. Default `3`. |
| `minRequestInterval` | number | Seconds between request starts. Default `0.4`. |

**A blank search is refused.** TMview treats an empty term as "match
everything" and reports 141 million results — this actor stops that before it
starts rather than billing you for a crawl of the world's registers.

### Output

Rows share one envelope, told apart by `recordType`: `TRADEMARK`,
`SEARCH_SUMMARY`, `ERROR`.

#### `TRADEMARK`

```json
{
  "_input": "apple",
  "recordType": "TRADEMARK",
  "resultRank": 1,
  "st13": "EM500000000218990",
  "markName": "APPLE",
  "office": "EM",
  "officeUrl": "https://www.tmdn.org/tmdsview-cdc/trademark/data/EM500000000218990",
  "applicationNumber": "000021899",
  "registrationNumber": "000021899",
  "status": "Registered",
  "markType": "Word",
  "applicantName": ["Apple Inc."],
  "niceClasses": [9],
  "protectedIn": ["EM"],
  "applicationDate": "1996-04-01",
  "registrationDate": "1998-11-25",
  "expirationDate": "2026-04-01",
  "markImageUrl": null
}
```

| Field | Type | Description |
|---|---|---|
| `st13` | string | TMview's stable identifier for the mark. |
| `markName` | string | The mark as registered. |
| `office` | string | Register holding it (`EM`, `US`, `CN`…). |
| `officeUrl` | string | Link to the full record. |
| `applicationNumber` / `registrationNumber` | string | Official numbers. |
| `status` | string | `Registered`, `Filed`, `Expired`, `Ended`… |
| `markType` | string | `Word`, `Figurative`, `Combined`… |
| `applicantName` | array | Owner(s) — an array, since marks can be co-owned. |
| `niceClasses` | array | Nice classes the mark covers. |
| `protectedIn` | array | Territories of protection. Differs from `office`: a WIPO filing is held at one office but protected in many. |
| `applicationDate` / `registrationDate` / `expirationDate` | string | `YYYY-MM-DD`. |
| `markImageUrl` | string | Image, **where one exists** — word marks have none. |

#### `ERROR`

Every search term produces at least one row, so a failure is visible in the data
rather than as an absence.

### Known limits

- **10,000 rows per query.** Explained above; split the search to go wider.
- **Not every register publishes every field.** Measured across a live sample:
  registration number ~90%, expiry date ~67%, mark image ~55% (word marks have
  none). Missing values come back as explicit nulls, so columns stay stable.
- **No goods & services text.** TMview's per-mark detail page is HTML, laid out
  differently by each of 70+ national offices, so this actor does not scrape it.
  You can still *filter* by goods & services text.
- **Statuses and types vary by office.** They are documented rather than
  enforced as a closed list, because national registers use their own wording —
  and an unrecognised value returns a clean zero, so a typo is visible.
- **Data is as current as each office's feed to TMview**, which varies by
  country.

### Attribution

Data via **TMview**, operated by the EUIPO with the participating national and
regional IP offices. TMview is a search tool: for legal certainty always confirm
against the official register, linked on every row as `officeUrl`.

# Actor input Schema

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

One brand name or word per entry — each gets its own search and its own summary row.

This is required. A blank search is not an error upstream: TMview treats it as a match-all query over its entire ~141 million mark index, so this actor refuses it rather than starting a crawl of the world's trademark registers by accident.

## `searchCriteria` (type: `string`):

How the term is matched against the mark name. Measured on `apple`: Contains 33,895 · Word match 21,946 · Begins with 14,701 · Fuzzy 28,226 · Exact 8,698.

## `offices` (type: `array`):

Two-letter office codes to restrict the search to. Leave empty for all 70+ registers.

Common codes: `EM` (EU/EUIPO), `WO` (WIPO international), `US`, `GB`, `DE`, `FR`, `ES`, `IT`, `CN`, `JP`, `KR`, `IN`, `BR`, `AU`, `CA`, `MX`, `TR`, `CH`.

An unrecognised code returns zero results rather than silently ignoring the filter, so a typo is visible in the data.

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

Nice Classification classes, 1–45 (e.g. `9` software/electronics, `25` clothing, `35` advertising/business, `42` scientific & IT services). Leave empty for all classes.

## `statuses` (type: `array`):

Restrict by status, e.g. `Registered`, `Filed`, `Expired`, `Ended`, `Withdrawn`, `Refused`, `Opposed`. Leave empty for all.

Not enforced as a fixed list because TMview federates 70+ national registers and any of them can use a status string not seen here — and an unknown value returns a clean zero rather than quietly widening the search.

## `markTypes` (type: `array`):

Restrict by mark type, e.g. `Word`, `Figurative`, `Combined`, `3-D`, `Sound`, `Colour`, `Hologram`, `Motion`, `Multimedia`. Leave empty for all.

## `goodsServices` (type: `array`):

Optional free-text terms matched against the goods and services description (e.g. `computer software`). Leave empty to search mark names only.

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

Results are fetched 100 per request. **TMview serves at most 10,000 rows per query** however many it reports as matching — that ceiling is upstream and no tool can exceed it. To go wider, split the search by office, Nice class or status; each combination is its own 10,000-row window. The summary row always reports both numbers.

## `maxConcurrency` (type: `integer`):

Upper bound on requests in flight at once, across all search terms. TMview is a public EUIPO service querying a federated index, so keep this modest.

## `minRequestInterval` (type: `number`):

Paces request starts without tying up a worker. Each request returns 100 marks, so a run needs few requests and there is no reason to go fast.

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

Off by default. TMview is a public EUIPO service with no bot protection and no IP gating, so a proxy adds latency without buying access.

## Actor input object example

```json
{
  "searchTerms": [
    "apple"
  ],
  "searchCriteria": "C",
  "offices": [],
  "niceClasses": [],
  "statuses": [],
  "markTypes": [],
  "goodsServices": [],
  "maxItems": 100,
  "maxConcurrency": 3,
  "minRequestInterval": 0.4,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `items` (type: `string`):

One row per scraped record. See the dataset's default view for field definitions.

# 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": [
        "apple"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapyx/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": ["apple"] }

# Run the Actor and wait for it to finish
run = client.actor("scrapyx/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": [
    "apple"
  ]
}' |
apify call scrapyx/trademark-search-scraper --silent --output-dataset

```

## MCP server setup

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