# EUIPO Trademark Search Scraper (`devilscrapes/euipo-trademark-search-scraper`) Actor

Search EUIPO and TMview trademarks by word: mark name, owner, status, Nice classes, application, registration and expiry dates, office and record URL. Filter by office, match mode and page depth, as clean deduplicated rows.

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

## Pricing

Pay per event

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

<p align="center">
  <img src=".actor/icon.svg" width="160" alt="Devil Scrapes mark" />
</p>

## EUIPO Trademark Search Scraper

**💰 $2.20 / 1 000 results**  ·  pay only for results  ·  no credit card to try

*The devil's in the data.* 😈

Search EUIPO and TMview trademarks by word and get clean, deduplicated
rows: mark name, owner, status, Nice classes, application, registration
and expiry dates, the registering office, and the record URL. EUIPO (the
EU trademark office) is the default; add national offices when you want
them.

### 🎯 What this scrapes

TMview is the joint trademark search of EUIPO and national offices, and
it has no bulk export. This Actor runs each word you give it, walks the
result pages thirty marks at a time, and returns one row per trademark:
the stable TMview `st13` id, mark name, office, application and
registration numbers, status, mark type, Nice classes, applicant names,
application / registration / expiry dates, opposition window, designated
territories, Vienna codes, and image links for figurative marks.

**Office scope.** By default the search is limited to the EUIPO office
(`EM`), and every row carries its `office` code so you can check it.
Pass other codes in `offices` (for example `DE`, `FR`, `ES`) to search
national registers too, or leave the list empty to search every office
TMview covers.

### 🔥 Features

- 🛡️ **We rotate browser fingerprints** (curl-cffi Chrome, Firefox and
  Safari impersonation) so the source sees a real browser's TLS
  handshake, not a Python script.
- 🔁 **We retry with exponential backoff** on rate limits and server
  errors, honouring `Retry-After`. Up to 5 attempts per page.
- 🌐 **We rotate proxy sessions** through Apify Proxy on every block,
  with a fresh session and exit IP each time.
- 🧊 **Run-wide deduplication.** The same `st13` never appears twice in
  your dataset, across pages or across queries in one run.
- 🎚️ **Match mode and office filters.** Contains, exact word, or fuzzy
  matching, over the offices you choose.
- 🧱 **Fault isolation.** One query that gets blocked doesn't end the
  others; we log it and keep going.
- 💰 **You pay only for results that land.** No data, no charge (only
  the small `actor-start` warm-up fee).

### 💡 Use cases

- **Brand protection teams:** watch for new filings that contain your
  brand name across the EU register.
- **Law firms and IP agents:** run clearance searches and export the
  hits with owners, classes and dates.
- **Naming and product teams:** check whether a candidate name is
  already taken in the classes you care about.
- **Data and analytics:** build trademark datasets by owner, class or
  filing date for dashboards.

### ⚙️ How to use it

1. Add one or more words to `queries`, for example `nike` or `adidas`.
2. Keep `offices` at `EM` for EUIPO, or add national office codes.
3. Set `maxPages` and `maxItems` to bound how much you pull.
4. Run it, then export to JSON, CSV, or Excel, or pull the dataset
   straight from the Apify API.

### 📥 Input

| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
| `queries` | `array<string>` | yes | `nike` | Words to search for in trademark names. |
| `offices` | `array<string>` | no | `["EM"]` | Office codes. `EM` is EUIPO. Empty searches every office. |
| `criteria` | `string` | no | `C` | `C` contains, `W` exact word, `F` fuzzy. |
| `maxPages` | `integer` | no | `3` | Pages fetched per query, 30 marks each (1-500). |
| `maxItems` | `integer` | no | `100` | Hard cap on total rows across the run (1-15000). |
| `proxyConfiguration` | `object` | yes | Apify Proxy | Apify Proxy configuration. |

#### Example input

```json
{
  "queries": ["nike", "adidas"],
  "offices": ["EM"],
  "criteria": "C",
  "maxPages": 2,
  "maxItems": 100,
  "proxyConfiguration": { "useApifyProxy": true }
}
```

### 📤 Output

One row per deduplicated trademark.

| Field | Type | Notes |
|---|---|---|
| `st13` | `string` | TMview ST13 id, the stable dedupe key. |
| `trademarkName` | `string \| null` | Word mark text. |
| `office` | `string` | Registering office code, for example `EM`. |
| `officeUrl` | `string \| null` | The office's own record URL. |
| `applicationNumber` / `registrationNumber` | `string \| null` | Office numbers. |
| `status` | `string \| null` | Registered, Filed, Expired, Ended and so on. |
| `trademarkType` | `string \| null` | Word, Figurative, Combined and so on. |
| `niceClasses` | `array<integer>` | Nice classification classes. |
| `applicants` | `array<string>` | Applicant / owner names. |
| `applicationDate` / `registrationDate` / `expirationDate` | `string \| null` | ISO-8601 dates. |
| `oppositionPeriodStart` / `oppositionPeriodEnd` | `string \| null` | Opposition window. |
| `designatedOffices` | `array<string>` | Territories the mark protects. |
| `viennaCodes` | `array<string>` | Vienna figurative-element codes. |
| `imageUrl` / `thumbnailUrl` | `string \| null` | Mark image links, figurative marks only. |
| `searchQuery` | `string` | Input query that produced this row. |
| `pageNumber` | `integer` | 1-based result page. |
| `scrapedAt` | `string` | UTC ISO-8601 run timestamp. |

#### Example output record

```json
{
  "st13": "EM500000006655302",
  "trademarkName": "NIKE",
  "office": "EM",
  "officeUrl": "http://euipo.europa.eu/trademark/data/EM500000006655302",
  "applicationNumber": "006655302",
  "registrationNumber": "006655302",
  "status": "Ended",
  "trademarkType": "Word",
  "niceClasses": [21],
  "applicants": ["Navipol sp. z o.o."],
  "applicationDate": "2008-02-08T12:00:00.000Z",
  "searchQuery": "nike",
  "pageNumber": 1,
  "scrapedAt": "2026-10-12T08:00:00Z"
}
```

### 💰 Pricing

Pay-Per-Event: you pay only when these events fire.

| Event | USD | What it is |
|---|---:|---|
| `actor-start` | $0.20 | One-off warm-up charge per run |
| `result-emitted` | $0.002 | Per deduplicated trademark row written to the dataset |

Example: 1 000 rows = **$2.20 per run** ($0.20 start + 1000 x $0.002).
No subscription, no minimum, no card required to try it.

### 🚧 Limitations

- **Search-listing fields only.** This returns what the TMview results
  list publishes. Goods and services text and full owner addresses sit
  on the office record pages and are out of scope.
- **Office scope is yours to set.** The default is EUIPO only (`EM`).
  Empty `offices` searches every office, so check the `office` column.
- **Result depth.** Each query pages thirty marks at a time; set
  `maxPages` high enough for the depth you need.
- **A query with no matches is a success.** It finishes with zero rows
  and a status message naming what was searched.

### ❓ FAQ

**Do I need an EUIPO account or API key?**
No. This reads the public TMview search.

**Is this EUIPO only?**
By default, yes: `offices` defaults to `["EM"]` and every row carries
its `office` so you can verify it. Add other office codes or empty the
list to widen the search.

**What do the match modes do?**
`C` finds marks containing your word, `W` finds the exact word, and `F`
adds fuzzy matches.

**Can I search several words in one run?**
Yes. Pass an array to `queries`; every row carries `searchQuery` so you
can tell which search found it.

**What happens if a search is blocked?**
We retry up to 5 times with a fresh browser fingerprint and proxy
session each time. If a query still can't be read, the others carry on
and the status message says so. The run ends as failed only when a query
was blocked and nothing at all could be collected.

**Can I run this on a schedule?**
Yes. Use Apify Schedules to re-run your watch list and catch new
filings.

### 💬 Your feedback

Found a bug, or need a field we don't return yet? Open an issue on the
Actor's Issues tab. We read every one.

# Changelog

This Actor's version history is a separate document: https://apify.com/devilscrapes/euipo-trademark-search-scraper/changelog.md

# Actor input Schema

## `queries` (type: `array`):

Words to search for in trademark names. Each query is paged separately.

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

TMview office codes to search. EM is EUIPO (the EU trademark office); add national offices such as DE, FR, ES, IT. Leave empty to search every office.

## `criteria` (type: `string`):

How the query is matched against mark names: contains, exact word, or fuzzy.

## `maxPages` (type: `integer`):

Cap on result pages fetched per query (30 trademarks per page).

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

Hard cap on total deduplicated trademark rows emitted across the whole run.

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

Apify Proxy configuration. The default datacenter proxy is enough for this source.

## Actor input object example

```json
{
  "queries": [
    "nike",
    "adidas"
  ],
  "offices": [
    "EM"
  ],
  "criteria": "C",
  "maxPages": 2,
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `datasetItems` (type: `string`):

All dataset items as JSON.

## `datasetItemsCsv` (type: `string`):

Same data exported to CSV.

## `datasetView` (type: `string`):

Open the run dataset in the Console.

# 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 = {
    "queries": [
        "nike",
        "adidas"
    ],
    "offices": [
        "EM"
    ],
    "criteria": "C",
    "maxPages": 2,
    "maxItems": 100,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("devilscrapes/euipo-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 = {
    "queries": [
        "nike",
        "adidas",
    ],
    "offices": ["EM"],
    "criteria": "C",
    "maxPages": 2,
    "maxItems": 100,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("devilscrapes/euipo-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 '{
  "queries": [
    "nike",
    "adidas"
  ],
  "offices": [
    "EM"
  ],
  "criteria": "C",
  "maxPages": 2,
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call devilscrapes/euipo-trademark-search-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,devilscrapes/euipo-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/9MgWTd8ut2xk3zMgt/builds/5qGBExizX1nmipWN2/openapi.json
