# Trademark Search: USPTO, EUIPO & UK IPO in One Call (`everyotherfriday/trademark-search`) Actor

Search US, EU and UK trademarks by mark or owner, with status, Nice classes and goods/services. Sources: TMview (EUIPN), www.tmdn.org/tmview, and the United States Patent and Trademark Office, www.uspto.gov.

- **URL**: https://apify.com/everyotherfriday/trademark-search.md
- **Developed by:** [Paul Vasquez](https://apify.com/everyotherfriday) (community)
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$8.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

## Trademark Search: USPTO, EUIPO and UK IPO

Search public trademark records by mark text or owner name and export a consistent dataset. This Python 3.12 actor combines the USPTO Trademark Search service with TMview for EUIPO and UK IPO. It needs no registry account or API key for its primary sources. Use it for brand research, monitoring lists, and preparing records for human review. Search results do not establish whether a proposed name is available or legally safe to use.

### Coverage and current availability

USPTO searches use the public website's Elasticsearch-shaped JSON service, discovered through its public configuration. EUIPO and UK IPO searches use TMview office codes EM and GB, respectively. These offices are requested separately, so an unavailable registry does not prevent another registry from returning records. The current TMview interface sends search fields at the top level and uses `criteria: "C"`; the older nested criteria example returns HTTP 400.

The primary endpoints were reachable during development on September 26, 2026. Live-run results and any degradation are recorded in VALIDATION.md. The optional USPTO TSDR serial fallback is **degraded**: its public endpoint returned HTTP 401 and an API-key requirement here. The actor does not supply keys. USPTO mark-text search remains best-effort because its website API, session rules, and access controls can change. It first fetches the homepage and retains public session cookies in memory; it does not solve challenges or bypass authentication.

> **Proxy required for EU/UK:** TMview (EUIPO and UK IPO) drops direct connections from cloud datacenters. Leave proxyConfiguration.useApifyProxy on (the default); standard datacenter proxies work.

### Input

`queries` is a required nonempty array of mark strings or owner names. `searchType` defaults to `mark`; choose `owner` to target the USPTO owner field or TMview applicant field. An eight-digit query in mark mode is treated as a USPTO serial number. Search matching follows each registry's text-search semantics, so results are not guaranteed to be exact string matches.

`registries` selects `uspto`, `euipo`, and/or `ukipo`, with all three selected by default. `status` accepts `all`, `live`, or `dead`, defaulting to `live`. Unknown status values are retained only for `all`. TMview status is filtered locally because the apparent A/I group codes returned misleading zero-result responses during inspection. Live includes pending applications as well as registrations; dead includes expired, ended, cancelled, withdrawn, refused, and abandoned records.

`niceClasses` optionally selects integer classes 1–45. Matching any selected class is sufficient. `maxResultsPerQuery` defaults to 50 and applies **per query, per selected registry**. Thus three registries can return up to 150 records for one query at the default cap. Duplicate application numbers are suppressed within each query and registry; the same record matching different input queries can appear and be charged again.

`includeGoods` defaults to true. It includes `goodsServices` and fetches TMview detail records, which can also improve owner country and status dates. Set it false for faster search-only results; the goods field is then omitted and some metadata may remain null. `timeoutSecs` defaults to 30 per network operation. `proxyConfiguration` accepts standard Apify proxy settings; no proxy is selected by default.

### Output and pricing

Each record contains registry, applicationNumber, registrationNumber, markText, markType, owner, ownerCountry, status, statusDate, filingDate, registrationDate, expiryDate, niceClasses, imageUrl, url, and source. Dates use YYYY-MM-DD where parseable. Numbers remain strings to preserve leading zeroes. Owners are joined with semicolons; country values retain source spelling. Missing information is null, and Nice classes are sorted unique integers. Every record also includes its input query.

A successfully persisted record triggers one `record-returned` event priced at **$0.008**. Twenty records cost $0.16; sixty cost $0.48. Dataset rows with `rowType: "summary"` are uncharged. These appear for zero matches or errors and include query, registry, count, error, elapsedSeconds, and chargeLimitReached. Key-value records SUMMARY and SUMMARY-N report every attempted query/registry combination, including successful ones.

If a detail request fails, the search record remains useful and is returned with `detailError`; it still costs one event. An uncharged summary discloses the incomplete enrichment. API errors and malformed responses are never presented as successful empty searches. Earlier results survive later pagination errors. The SDK's charged dataset write handles remaining event limits and stops further work once the limit is reached.

### Running and maintaining

Create a Python 3.12 virtual environment, install requirements.txt, and run `python -m unittest discover -s tests -v`. Validate the input with `apify validate-schema .actor/input_schema.json`. On Windows, `validation/run_live.ps1` copies INPUT.json into isolated local storage, executes `python -m src`, and saves timings and counts to validation/results.json. Local runs do not bill.

HTTP 403 and 429 responses receive two retries with exponential backoff; numeric Retry-After delays are capped at 30 seconds. Transport errors also receive two retries. Searches stop at the requested result cap, USPTO's 10,000-result window, or TMview's 500-page safety limit. Narrow broad owner queries when necessary. Goods descriptions and status mappings reflect public source data, which may lag official changes. Before deployment, configure the sole custom pricing event in Console and disable synthetic start/dataset charges. This repository task does not publish or push the actor.

### Example output

One real saved dataset row, trimmed by omitting fields only. Source: `storage/live-20260926-044804/datasets/default/000000001.json`. This is historical validation evidence, not a live response.

```json
{
  "registry": "uspto",
  "applicationNumber": "50086128",
  "registrationNumber": null,
  "markText": "NIKE",
  "owner": "Nike, Inc. (CORPORATION; Oregon, USA)",
  "status": "live",
  "filingDate": "2026-09-02",
  "niceClasses": [
    16
  ],
  "query": "nike"
}
```

This is a saved search result, not a fresh registry status check. The null registration number is preserved; live status can include an application. Fields omitted for space remain available in the full dataset row.

### Use cases

- A brand naming agency can assemble candidate-name search records across the three registries for a client review meeting.
- An in-house trademark operations team can export owner-query results into a monitoring worksheet, preserving registry and application identifiers.
- An ecommerce brand manager can collect records in selected Nice classes for discussion with trademark counsel before a packaging decision.
- A licensing research firm can organize applicant names and available goods descriptions into a source-linked research shortlist.

**Pricing example:** 1,000 successful `record-returned` events x $0.008 = **$8.00**, computed from `.actor/pay_per_event.json`. This is the declared event subtotal; it does not verify active hosted billing or include any separately applicable platform or proxy costs.

### Limitations

Search results are research inputs, not trademark clearance or a legal availability decision. Registry matching rules, caps, delayed updates, and failed detail requests can affect coverage. The TSDR fallback was degraded in local validation. For EU/UK cloud runs, follow the proxy guidance above and inspect the actual input configuration.

### Sources and credit

EU and UK records: TMview (EUIPN), www.tmdn.org/tmview. The information is freely available at the source. United States records: United States Patent and Trademark Office, www.uspto.gov. Trademark data is public register data, and this Actor is not affiliated with or endorsed by either office.

This Actor is built for lookups and monitoring of specific marks and owners, not for bulk copies of a register. Keep result caps modest. If you need a full register, use the offices' own bulk data products.

# Actor input Schema

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

Mark text or owner names. Eight-digit USPTO mark queries are treated as serial numbers.

## `searchType` (type: `string`):

Search mark text or applicant/owner names.

## `registries` (type: `array`):

Registries to search independently; cap applies per query per registry.

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

Normalized live/dead status; unknown statuses are included only with all.

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

Optional classes 1 through 45. A record matching any selected class is included.

## `maxResultsPerQuery` (type: `integer`):

Maximum matching unique rows per query for each selected registry.

## `includeGoods` (type: `boolean`):

Include goodsServices text and retrieve TMview details, including owner country when available.

## `timeoutSecs` (type: `integer`):

Timeout per HTTP operation; blocked requests receive two retries.

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

Proxy settings. Keep Apify Proxy on: the EU/UK TMview registry blocks direct datacenter traffic, and datacenter proxy groups are enough (residential not needed).

## Actor input object example

```json
{
  "searchType": "mark",
  "registries": [
    "uspto",
    "euipo",
    "ukipo"
  ],
  "status": "live",
  "maxResultsPerQuery": 50,
  "includeGoods": true,
  "timeoutSecs": 30,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

Normalized records and uncharged summary rows.

## `recordsCsv` (type: `string`):

Same dataset as CSV.

## `summaries` (type: `string`):

SUMMARY and SUMMARY-N keys with counts, timings and errors.

# 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 = {
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("everyotherfriday/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 = { "proxyConfiguration": { "useApifyProxy": True } }

# Run the Actor and wait for it to finish
run = client.actor("everyotherfriday/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 '{
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call everyotherfriday/trademark-search --silent --output-dataset

```

## MCP server setup

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