Brand Name IP Screener avatar

Brand Name IP Screener

Pricing

from $1,000.00 / 1,000 name screened in one jurisdictions

Go to Apify Store
Brand Name IP Screener

Brand Name IP Screener

Screens brand names vs curated famous-mark seed datasets (not full registry) for trademark-collision risk across FR/US/EU/WO/UK — visual + phonetic similarity scoped to Nice classes, with a domain co-check. Clear/caution/high-risk per jurisdiction. Informational only — not legal advice.

Pricing

from $1,000.00 / 1,000 name screened in one jurisdictions

Rating

0.0

(0)

Developer

Protocol

Protocol

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

7 days ago

Last modified

Share

Generate brand-name candidates from a positioning brief, or screen names you already have, for trademark-collision risk — with France (INPI) and the EU (EUIPO) covered first, plus the US (USPTO), UK (UKIPO), and international (WIPO) — then get a domain-availability check and a collision-risk verdict in one run — clear (no collision found among the marks screened), caution, or high-risk. Each jurisdiction is screened against a curated famous-mark seed dataset, not full registry coverage — this is a pre-filing risk triage, not a substitute for a full-registry clearance search. Unlike a domain checker (which only asks "is the URL free?"), this asks the harder question a trademark examiner asks: is this name confusingly similar — including phonetically (sounds-alike) — to an existing registered mark in my class of goods/services?

  • Generate + screen + rank in one run — not just an LLM prompt, not just a trademark search.
  • 5 jurisdictions: France (INPI) and the EU (EUIPO) first, then US (USPTO), UK (UKIPO), and International (WIPO) — each screened against a curated dataset of well-known, real registered marks.
  • Visual + phonetic similarity, the way examiners assess likelihood of confusion — not just spelling. Teslaa is correctly flagged against Tesla even though it isn't a substring match.
  • Domain co-check — probes .com, .io, .ai, .dev via RDAP in the same run.
  • Agent-ready: flat CSV-friendly dataset plus a structured OUTPUT record per name, each carrying a mandatory "not legal advice" disclaimer.

Informational screening only — not legal advice. Registry-free ≠ trademark-free ≠ right-to-use. Clearance requires a qualified trademark attorney. This disclaimer ships on every result.


Quick start

  1. Create a free Apify account (or sign in).
  2. Open this Actor's page and go to the Input tab.
  3. Either add at least one name under names (screen mode), or fill in positioning (generate mode) — exactly one of the two is required.
  4. Click Start and wait a few seconds.
  5. Open the Storage tab to view the per-jurisdiction dataset, or read the OUTPUT key-value record for the full structured verdict per name.

What this Actor does

Screen mode (names set):

  1. Normalizes each name (lowercase, diacritics folded, legal suffixes stripped) to its distinctive core.
  2. Screens it against every selected jurisdiction's curated mark dataset, scoring visual similarity (Damerau-Levenshtein) and phonetic similarity (Double Metaphone, English + French) in parallel and fusing the two into a 0–100 ipRiskScore.
  3. Scopes to Nice classes — your goods/services classes 1–45, either supplied directly or inferred from a free-text industry field.
  4. Co-checks domain availability via RDAP across 5 TLDs (optional, on by default).
  5. Writes a flat dataset (one row per name × jurisdiction) plus a structured OUTPUT record per name with an overall brandReadiness verdict and a human-readable recommendation.

Generate mode (positioning set instead of names) does all of the above, plus runs it as a closed loop:

  1. Generates candidate names from your positioning brief via an LLM (DeepSeek primary, GPT-4o-mini fallback via OpenRouter).
  2. Filters them deterministically — profanity, banned words, duplicates, and your mustInclude/avoid constraints (enforced after generation, not just asked of the model) — entirely locally, zero network calls for this stage.
  3. Screens every survivor through the exact same pipeline as screen mode above.
  4. Ranks them by a composite score: naming quality × (1 − ipRisk) × domain availability — so the names at the top of the list are good and show low collision risk in the screened seed and are actually available.

Why use it

  • Catch what a spelling check misses. Phonetic matching flags sounds-alike collisions (Brandcraft vs Brandkraft) that a substring or Levenshtein-only check would pass clean.
  • Don't waste a clearance search on a taken domain. The RDAP co-check runs in the same pass.
  • Skip the false sense of security. Jurisdictions with no enabled data source report not_screened, and every clear carries a marksScreened count so a weak clear can't pass for a strong one — this Actor never returns a false clear.
  • Generate names that are actually usable, not just names that sound good — generate mode ranks by ownability, not just LLM creativity.

How this compares

This Actor screens brand names against a curated seed of well-known, real registered marks per jurisdiction (FR/US/EU/WO/UK), scores visual + phonetic similarity scoped to your Nice classes, co-checks domain availability via RDAP, and returns a clear / caution / high-risk verdict in seconds. It is informational screening, not legal advice — read every verdict as "no collision found among the marks screened," never as "trademark-free" or "safe to launch."

OptionWhat you getCost / speedHonest limits
This ActorAutomated, scored screening across 5 jurisdictions, visual + phonetic, Nice-class-scoped, plus RDAP domain co-check, in one run.Seconds; ~$1/name×jurisdiction screened (generate mode is free).Curated famous-mark seed, not the full registry. "No collision found" means among the marks screened — a real register may hold a conflicting mark outside the sample. Informational only; not a clearance opinion.
$150–$300 paralegal / trademark-attorney clearanceAn authoritative, jurisdictionally complete clearance opinion from a qualified attorney who searches the full register, weighs likelihood of confusion in light of case law, and advises on filing strategy.$150–$300+; hours to days.Slower and more expensive. Authoritative where this Actor is probabilistic — the right step before you file or invest.
Manual searching of EUIPO eSearch Plus / TMview / USPTO / INPIFree, direct access to the live registries.Free; slow — minutes-to-hours per name per jurisdiction, and you do all the scoring yourself.Un-scored: you eyeball similarity and easily miss visual/phonetic near-misses (Teslaa vs Tesla, Brandkraft vs Brandcraft). No Nice-class scoping unless you filter by hand. No domain co-check. Easy to conclude "no match found" when a sounds-alike collision is one tab over.
Doing nothing (blind launch)Nothing.$0 upfront.Highest downstream risk: a cease-and-desist, opposition, or rebrand after you've already invested in marketing, inventory, or filings.

When to pick what

  • Use this Actor first to triage a long list cheaply — drop obvious collisions, rank what's left, and find out which names are even worth paying a human to clear. A high-risk verdict here is a strong signal to drop or rename; a clear is "no collision found in the curated seed," not a green light.
  • Engage a qualified trademark attorney before you file, invest, or launch — especially for any name this Actor scored caution or high-risk, and for any name you can't afford to rebrand later. The attorney's clearance is the authoritative step this Actor deliberately does not replace (see the attorneyReview flag on every result).
  • Manual registry searching is free and worth doing as a second opinion on a shortlisted name, but it doesn't replace scored similarity (you'll miss phonetic near-misses) and it doesn't scale past a name or two.
  • Doing nothing is the only option that costs nothing upfront and exposes you to the full cost of a collision discovered after launch.

Informational screening only — not legal advice. "Low collision risk found in the curated seed" and "no collision found among the marks screened" are probabilistic observations from a famous-mark sample, not a guarantee of right-to-use. Clearance requires a qualified trademark attorney.


Complete the funnel

A name that screens with low collision risk still needs handles. Once this Actor ranks your candidates, check whether the matching usernames are free across GitHub, X, Instagram, Threads, TikTok, Twitch, and YouTube with the sibling AI Username Generator & Availability Checker Actor (Protocol/username-generator-checker) — the next step in the same naming workflow. Generate there, or validate a name you already have, and finish the name → trademark screen → handle + domain check loop in two paid runs.

Same "not legal advice" boundary: handle availability is a separate signal from trademark right-to-use. Both still require a qualified attorney's clearance before you file.


Pricing

This Actor is billed on pay-per-event (PPE) — you pay for value milestones, not compute time. There is no rental fee and no subscription; you only pay for the billable events below.

EventWhen it firesPrice
screening_report_producedScreen mode — one name fully screened across all your selected jurisdictions, with the structured OUTPUT verdict written. Billed per name × jurisdiction that returns screened (i.e. a real collision check ran).$1.00
candidate_generated_and_rescreenedGenerate mode — one candidate that survived the deterministic filter (profanity / banned-word / duplicate) and was screened through the full IP + RDAP pipeline.$0.00

What you never pay for:

  • Generate mode — it is free. Name generation and the full IP + RDAP screening of every generated candidate cost nothing, in any number of jurisdictions (see below).
  • Jurisdiction rows that report not_screened (no enabled data source) — never billed, never a false clear.
  • Candidates in generate mode that the Tier-1 filter rejected — they're listed under OUTPUT.filtered at no charge.
  • Compute time, retries, or LLM fallback attempts that don't produce a result.

Worked examples (launch pricing, set in the Apify Console; 14 days' notice is given before any change, max once per month):

  • Screen 3 names across ["FR", "US", "EU"] → 3 × 3 = 9 screened rows → $9.00.
  • Generate mode, count: 10, 2 candidates filtered out → 8 candidates generated + rescreened → $0.00.
  • Screen 1 name across 5 jurisdictions where UK has no enabled source → 4 screened rows + 1 not_screened → billed for 4 → $4.00.

Generate mode is free. candidate_generated_and_rescreened is priced at $0.00, no matter how many candidates you generate or how many jurisdictions you screen them across. Generate-mode runs supply their own LLM key (or provider subscription) via llmApiKey, so this Actor carries no inference cost to pass on. The event still fires at $0 so generate-mode usage stays visible in your run's charge breakdown. Pricing may change in a future version (14 days' notice, as above).

Clearance-grade screening at a fraction of a $200+ paralegal search. Pricing is indicative at launch and finalized in the Console before publication.

Set "Maximum cost per run" high enough for the whole batch. Screen mode costs $1.00 × names × jurisdictions, so 2 names × 5 jurisdictions is $10.00. If the run's cost cap is reached mid-batch, the Actor stops screening the remaining names and reports them as not_screened with reason budget_exhausted — it never silently returns a clear it did not verify, and the unscreened names are never charged. That is the safe failure mode, but it does mean a cap set below the batch total gives you a partial report. Either raise the cap (or leave it unlimited) or split the batch.


Supported jurisdictions

JurisdictionRegistryCoverage
FRINPI (France)Curated seed dataset of 163 well-known, real registered marks (software/SaaS, e-commerce, finance, food/beverage, fashion, cosmetics, automotive, media, telecom, transport, pharma, furniture, education, real estate, travel)
USUSPTOCurated seed dataset of 203 well-known, real registered marks (tech, fintech, retail, food/beverage, telecom, pharma, automotive, media, hospitality, education)
EUEUIPOCurated seed dataset of 201 well-known, real registered marks (EU-headquartered companies + global brands' EU Trade Mark registrations across tech, automotive, luxury/fashion, food/beverage, finance, pharma, retail, travel, media)
WOWIPO (Madrid System)Curated seed dataset of 321 well-known marks, mostly Asia-headquartered multinationals (electronics, automotive, retail, internet services, finance, industrial)
UKUKIPOCurated seed dataset of 300 well-known, real registered marks (banking/finance, retail/fashion, telecom/media, travel/hospitality, tech, energy/industrial, pharma)

"Curated seed dataset" means famous-mark collision screening, not full registry coverage. Each registry holds millions of marks; this Actor ships a hand-picked sample of well-known ones per jurisdiction, real and currently registered. Full bulk ingestion (INPI ~3.1 GB on data.gouv.fr; USPTO bulk XML/TSV since TSDR is status-by-number only; EUIPO eSearch Plus OAuth2; WIPO Global Brand Database; UKIPO bulk data / TMview) is a larger, separate undertaking. A jurisdiction in jurisdictions with no enabled source reports screeningStatus: "not_screened" — never a false clear.


Input

Exactly one of names / positioning is required.

FieldTypeDefaultDescription
namesstring[]Proposed names to screen (≤20). Leave empty and set positioning instead to generate names first.
jurisdictionsstring[]["FR"]Any of FR, US, EU, WO, UK.
niceClassesstring[][]Your goods/services classes 1–45. Recommended — scoping removes noise. Leave empty (with industry set) to auto-infer.
industrystringFree-text sector, e.g. "fintech". Drives Nice-class inference (when niceClasses is empty) and the human-readable recommendation.
language"en" | "fr""en"Drives the phonetic encoder.
riskThresholdinteger60Minimum similarity (0–100) for a mark to be listed in the output.
enableDomainCheckbooleantrueRuns the RDAP co-check across .com/.io/.ai/.dev.

Generation-mode fields (only used when positioning is set)

FieldTypeDefaultDescription
positioningstringFree-text brand positioning / value proposition. Setting this (with names empty) switches the run to generate mode.
toneenumProfessionalOne of Professional, Playful, Premium, Technical, Friendly.
techniquesstring[][]Naming techniques to bias toward, e.g. ["compound", "invented"]. Empty = let the model choose.
mustInclude / avoidstring[][]Fragments every generated name must contain at least one of / must never contain. Enforced deterministically after generation (not just asked of the model); rejects are free.
countinteger10How many names to generate before filtering (hard cap 20).
maxLengthinteger18Max generated-name length, excluding spaces (hard cap 30).
bannedWordsstring[][]Extra words to reject beyond the built-in profanity list.

Bring-your-own LLM (v1.8.0)

Generate mode needs an LLM key. There are two ways to supply one — per-run user overrides win, the operator env var is the fallback:

FieldTypeDefaultDescription
llmProviderenumopenaiopenai = any OpenAI-compatible endpoint (OpenRouter, OpenAI, Groq, Ollama, LM Studio). anthropic = native Claude Messages API.
llmApiKeystringYour own provider API key (marked secret — never logged). Overrides the operator's OPENROUTER_API_KEY.
llmBaseUrlstringprovider defaultProvider endpoint, HTTPS (plain HTTP only for localhost). Overrides OPENROUTER_BASE_URL.
llmModelstringoperator defaultSingle model id used for both primary and fallback. Examples: anthropic/claude-3.5-sonnet (OpenRouter), llama-3.3-70b-versatile (Groq), gpt-4o-mini (OpenAI), claude-haiku-4-5-20251001 (Anthropic).

If you supply llmApiKey, you pay your own LLM provider directly. If you leave these blank, the run uses the operator-configured OPENROUTER_API_KEY (the Actor owner's) — but only on the default OpenRouter endpoint with the default openai provider. Setting llmBaseUrl to any non-default endpoint, or llmProvider to anthropic, requires your own llmApiKey: the operator's key is never transmitted to a custom endpoint or a non-default provider (key custody). A run that omits it fails fast with ERR_MISSING_API_KEY — it never silently falls back to the operator key. Screen-only runs (names set) never read any key.

Provider examples (set as input, or as the operator env vars):

// Groq (fast + cheap) — OpenAI-compatible
{ "llmProvider": "openai", "llmApiKey": "gsk_…", "llmBaseUrl": "https://api.groq.com/openai/v1/chat/completions", "llmModel": "llama-3.3-70b-versatile" }
// OpenAI direct
{ "llmProvider": "openai", "llmApiKey": "sk-…", "llmBaseUrl": "https://api.openai.com/v1/chat/completions", "llmModel": "gpt-4o-mini" }
// Anthropic (native Claude API) — no OpenRouter middleman
{ "llmProvider": "anthropic", "llmApiKey": "sk-ant-…", "llmModel": "claude-haiku-4-5-20251001" }
// OpenRouter (operator default) — leave llm* blank, or set your own OpenRouter key
{ "llmProvider": "openai", "llmApiKey": "sk-or-…", "llmModel": "anthropic/claude-3.5-sonnet" }

If neither a user llmApiKey nor the operator OPENROUTER_API_KEY is set, generate mode fails fast with ERR_MISSING_API_KEY — it never silently falls back to a weaker model.

Example input — screen mode

{
"names": ["Teslaa", "Acme"],
"jurisdictions": ["FR", "US", "EU"],
"niceClasses": ["9", "12", "42"]
}

Example input — generate mode

{
"positioning": "a calmer way to manage freelance invoices",
"industry": "fintech",
"tone": "Professional",
"count": 10
}

Output

The Actor writes to two places:

  1. Dataset — one row per name × selected jurisdiction.
  2. Key-value store OUTPUT{ schemaVersion, runId, mode, records[], filtered[]? }. This is the record AI agents should read first; mode is "screen" or "generate", and filtered is only present in generate mode.

Dataset fields

FieldMeaning
name / normalizedNameThe screened name, and its normalized comparison form.
jurisdictionFR / US / EU / WO / UK.
sourceRegistry label, e.g. "INPI".
screeningStatus"screened" or "not_screened" — never a false clear.
risk"clear" / "caution" / "high-risk" / "not_screened".
ipRiskScore0–100 collision risk for this jurisdiction; higher = more likely to conflict.
topSimilarMark / topSimilarityThe closest colliding mark and its 0–100 similarity score, or null.
similarMarksJsonJSON-encoded array of all similar marks with their visual/phonetic breakdown.
niceClasses / niceClassesSourceClasses the screening was scoped to, and whether they were user-supplied or inferred from industry.
marksScreenedHow many in-scope marks were actually scored for this row (coverage honesty). A clear over 3 marks ≠ a clear over 150. 0 when not_screened.
notScreenedReasonTyped reason when screeningStatus is not_screened (no_source / name_not_latin_screenable / name_has_no_distinctive_core / budget_exhausted / source_error / confusable_script); null when screened.
runIdApify run ID for traceability.
disclaimerThe mandatory "not legal advice" disclaimer.

Structured OUTPUT record fields

Each item in records[] carries: schemaVersion, name, normalizedName, brandReadiness (worst risk band across all screened jurisdictions), ipRiskScore, recommendation (human-readable), jurisdictions[] (per-jurisdiction verdict + similar marks, each with marksScreened — the in-scope mark count behind that verdict), niceClassesSource, matchedKeywords (the industry keywords that matched when classes were inferred; empty when user-supplied), domainAvailability ({ tlds, results[], summary: { free, taken, error } }), attorneyReview ({ recommended, message } — informational escalation only, see FAQ), seedAsOf (the YYYY-MM the curated famous-mark seeds were last verified — the seeds are point-in-time, not a live registry), and disclaimer.

In generate mode, each record additionally carries a generation block (technique, brandFit, readability, memorability, compositeScore), and records[] is sorted by compositeScore descending. Candidates rejected by the Tier-1 filter (profanity / banned word / duplicate / missing_required_fragment / forbidden_fragment) never reach the screen — they're listed separately under OUTPUT.filtered as { name, normalizedName, invalidReason }.

Example output — screen mode

Real run: { "names": ["Teslaa"], "jurisdictions": ["FR"] } correctly flags a phonetic collision with the real seed mark Tesla (visual similarity alone would score this lower; phonetics catch it):

{
"schemaVersion": "1.6.0",
"name": "Teslaa",
"normalizedName": "teslaa",
"brandReadiness": "high-risk",
"ipRiskScore": 92,
"recommendation": "High collision risk: \"Teslaa\" is phonetically close to \"Tesla\" (INPI, classes 12/9). Get trademark clearance before filing or investing in the name.",
"jurisdictions": [
{
"jurisdiction": "FR",
"source": "INPI",
"screeningStatus": "screened",
"risk": "high-risk",
"ipRiskScore": 92,
"marksScreened": 163,
"similarMarks": [
{
"mark": {
"mark": "Tesla",
"jurisdiction": "WO",
"niceClasses": [12, 9],
"status": "registered",
"owner": "Tesla, Inc."
},
"score": 92,
"similarity": { "visual": 83, "phonetic": 100 },
"signal": "phonetic"
}
]
}
],
"niceClassesSource": "inferred",
"matchedKeywords": ["automotive"],
"domainAvailability": {
"tlds": ["com", "io", "ai", "dev"],
"results": [
{ "domain": "teslaa.com", "tld": "com", "status": "taken" },
{ "domain": "teslaa.io", "tld": "io", "status": "available" },
{ "domain": "teslaa.ai", "tld": "ai", "status": "available" },
{ "domain": "teslaa.dev", "tld": "dev", "status": "available" }
],
"summary": { "free": 3, "taken": 1, "error": 0 }
},
"attorneyReview": {
"recommended": true,
"message": "High collision risk detected. We recommend engaging a qualified trademark attorney for a full clearance opinion before filing or investing further in this name. This screening is informational only and does not constitute legal advice."
},
"disclaimer": "Informational screening only — not legal advice. Registry-free ≠ trademark-free ≠ right-to-use. Clearance requires a qualified trademark attorney."
}

Example output — generate mode

Real run: { "positioning": "a calmer way to manage freelance invoices", "count": 2 }. Note brewforge outranks alphavault despite a lower brandFit — its higher readability and memorability win out in the composite:

{
"schemaVersion": "1.6.0",
"runId": "abc123",
"mode": "generate",
"records": [
{
"name": "brewforge",
"normalizedName": "brewforge",
"brandReadiness": "caution",
"ipRiskScore": 42,
"generation": {
"technique": "compound",
"brandFit": 90,
"readability": 87,
"memorability": 85,
"compositeScore": 51
}
},
{
"name": "alphavault",
"normalizedName": "alphavault",
"brandReadiness": "caution",
"ipRiskScore": 43,
"generation": {
"technique": "compound",
"brandFit": 85,
"readability": 88,
"memorability": 80,
"compositeScore": 48
}
}
],
"filtered": [
{ "name": "AlphaVault", "normalizedName": "alphavault", "invalidReason": "duplicate" },
{ "name": "shitstorm", "normalizedName": "shitstorm", "invalidReason": "profanity" }
]
}

(jurisdictions, domainAvailability, niceClassesSource, attorneyReview, and disclaimer are present on every record exactly as in screen mode — omitted above for brevity.)


How it works

  • Visual similarity — Damerau-Levenshtein edit distance on the normalized form (handles transpositions, not just insert/delete/substitute).
  • Phonetic similarity — Double Metaphone for English; a French pre-processing pass (silent finals, nasal vowels, ph/ch/qu digraphs) feeding the same encoder for French. Each name gets a [primary, secondary] code pair; the max-of-pairs comparison means a partial match in either code still scores above zero.
  • Fusion — visual and phonetic scores are combined into one ipRiskScore, scoped to the requested Nice classes, with banding into clear (no collision found in the screened seed), caution, or high-risk.
  • Domain check — RDAP (the IETF successor to WHOIS) queried directly per TLD, bounded concurrency, with a timeout; network failures degrade to error entries and never throw.
  • Generation — an OpenRouter-routed LLM (DeepSeek primary, GPT-4o-mini fallback, one retry on malformed JSON before falling back, schema-validated output) proposes names against your positioning brief; everything downstream runs through the same deterministic filter and screening pipeline as screen mode.

Usage via API

Run the Actor programmatically with the Apify API client. Use Protocol/brand-name-ip-screener as this Actor's ID, and supply your Apify API token.

Python

$pip install apify-client
from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_API_TOKEN>")
run_input = {
"names": ["Teslaa", "Acme"],
"jurisdictions": ["FR", "US", "EU"],
"industry": "fintech",
}
run = client.actor("Protocol/brand-name-ip-screener").call(run_input=run_input)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["name"], item["jurisdiction"], item["risk"], item["ipRiskScore"])
output = client.key_value_store(run["defaultKeyValueStoreId"]).get_record("OUTPUT")
print(output["value"])

JavaScript / TypeScript

$npm install apify-client
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_API_TOKEN>' });
const run = await client.actor('Protocol/brand-name-ip-screener').call({
positioning: 'a calmer way to manage freelance invoices',
industry: 'fintech',
count: 10,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.table(items.map((i) => ({ name: i.name, jurisdiction: i.jurisdiction, risk: i.risk })));

cURL

curl -X POST "https://api.apify.com/v2/acts/Protocol~brand-name-ip-screener/run-sync-get-dataset-items?token=<YOUR_APIFY_API_TOKEN>" \
-H 'Content-Type: application/json' \
-d '{ "names": ["Brandcraft"], "jurisdictions": ["FR"] }'

Use with AI agents (MCP)

The Actor is built to be driven by AI agents. INPUT_SCHEMA.json exposes typed fields with enum dropdowns and defaults, so an MCP client (e.g. Claude Desktop via the Apify MCP Server) can call it with minimal prompting. Agents should read the structured OUTPUT record — it carries brandReadiness, recommendation, and attorneyReview per name, so the agent doesn't have to reduce the flat dataset itself. Invalid input returns a structured error code rather than a silent failure (see Run-level error codes).

{
"mcpServers": {
"apify": {
"command": "npx",
"args": [
"mcp-remote",
"https://mcp.apify.com/?tools=Protocol/brand-name-ip-screener",
"--header",
"Authorization: Bearer <YOUR_APIFY_API_TOKEN>"
]
}
}
}

Tool-call example (screen mode)

Once the apify MCP server above is connected, an agent invokes the screener as a tool call. The tool name exposed by the Apify MCP Server is the Actor identifier (Protocol/brand-name-ip-screener); the argument is the same input shape as Example input — screen mode.

// Agent → MCP tool call
{
"tool": "Protocol/brand-name-ip-screener",
"input": {
"names": ["Teslaa", "Acme"],
"jurisdictions": ["FR", "US", "EU"],
"niceClasses": ["9", "12", "42"],
"enableDomainCheck": true
}
}

The tool returns the flat per-name × jurisdiction dataset rows plus a reference to the OUTPUT key-value record. Agents should read OUTPUT first — it carries the per-name brandReadiness, recommendation, and attorneyReview verdicts so the agent does not have to reduce the flat dataset itself. See Branching on the OUTPUT record for the decision fields, and Run-level error codes for the coded failure shape. Invalid input returns a coded error (e.g. ERR_INVALID_INPUT) rather than a silent failure — branch on the ERR_* prefix, not on free text.

Branching on the OUTPUT record (agent guidance)

When driving this Actor from a tool-calling agent, branch on these fields rather than free-text parsing:

  • brandReadiness — the overall verdict across all screened jurisdictions: clear | caution | high-risk | not_screened. Treat not_screened as "no signal", not as "safe" — it means no registry source ran for this name.
  • jurisdictions[].screeningStatusscreened vs not_screened per jurisdiction. Only screened rows were actually compared against marks; a not_screened row carries a reason (No data source enabled…, name_not_latin_screenable, name_has_no_distinctive_core, or budget_exhausted).
  • jurisdictions[].marksScreened — the denominator behind each verdict: how many in-scope marks were actually scored. A clear over 3 marks is not the same confidence as a clear over 150. Weight a clear by marksScreened before reporting low collision risk — a clear is "no collision found among the marks screened", not a promise of clearance.
  • niceClassesSource + matchedKeywords — whether the Nice-class scope was user-supplied or inferred from industry, and which industry keywords matched. If inferred and matchedKeywords is empty, the screen ran across all classes (noisier) — consider asking the user for explicit niceClasses before relying on a clear as a low-collision signal.
  • attorneyReview.recommended — a structured boolean for high-risk escalation messaging (informational only; no referral, see FAQ).
  • domainAvailability.summary{ free, taken, error } across .com/.io/.ai/.dev.

Billing per event: every screened jurisdiction in screen mode bills screening_report_produced ($1.00). Generate mode is free — every filter-survivor emits candidate_generated_and_rescreened at $0.00. not_screened rows and filter rejects are free too. If cost matters, scope with niceClasses and limit jurisdictions.


Run-level error codes

Every run failure exits with a coded Actor.fail message prefixed by an ERR_* code, so an MCP agent can branch deterministically rather than parsing free text. The table below enumerates every code defined in src/lib/errors.ts plus the runtime catch-all emitted by src/main.ts.

CodeMeaningWhen it firesWhat an agent consumer should do
ERR_INVALID_INPUTInput failed schema validation; names and positioning were both empty OR both set; or a niceClasses entry was not an integer in 1–45.At input validation, before any network/billing work. Raised by src/input/validate.ts (InvalidInputError).Surface to user + retry. Do not retry the same payload. Ask the user to fix the flagged field(s), set exactly one of names / positioning, or correct niceClasses. No charge has been made.
ERR_MISSING_API_KEYGenerate mode was requested but no LLM key is configured — neither a user llmApiKey nor the operator OPENROUTER_API_KEY. Also raised when a custom llmBaseUrl or non-default llmProvider is set without its own llmApiKey (the operator key is never sent to a custom endpoint — key custody).At LLM router init, generate mode only. Raised by src/generation/router.ts (MissingApiKeyError). Screen-only runs never hit this.Surface to user + retry. Ask the user for a llmApiKey (bring-your-own), or to switch back to the default openai provider + default endpoint so the operator key can be used.
ERR_LLM_PIPELINE_FAILEDBoth the primary and fallback LLM models failed or timed out (generate mode only).After both generation attempts exhaust retries / timeout / malformed-JSON recovery in src/generation/router.ts (LlmPipelineError).Retry once with backoff, then surface to user. If it persists, suggest a different llmModel / provider, or fall back to screen mode by supplying names directly.
ERR_REGISTRY_SOURCEA registry mark source threw (network / parse / auth failure) for a jurisdiction.Re-thrown by src/registry/seedAdapter.ts (RegistrySourceError) when a MarkSource rejects; caught per-jurisdiction in src/main.ts, which surfaces that jurisdiction as not_screened with reason source_error and logs it. The run continues.Partial result. Treat the affected jurisdiction as not_screened (no verdict), not as clear. Retry the run; if it persists for one jurisdiction only, screen without it or report via the Issues tab.
ERR_OUTPUT_SCHEMA_VIOLATIONAn internal output record did not match the declared dataset / OUTPUT schema.Raised by src/output/datasetValidator.ts (OutputSchemaViolationError) right before Actor.pushData, after AJV-validating every flat dataset row against the published .actor/dataset_schema.json (B4). The run fails the moment a row breaks the public contract.Stop + report. This is an actor-side defect, not a user-input issue. Do not retry the same input; surface the run id to the user and direct them to the Actor's Issues tab.
ERR_UNEXPECTEDAny non-coded throw after Actor.init — an unanticipated runtime failure (network blip, adapter crash, etc.).Catch-all in src/main.ts: any Error without an ERR_* code is wrapped in a typed UnexpectedError (src/lib/errors.ts, exported from ERROR_CODES.UNEXPECTED since B4) before Actor.fail, then rethrown so the platform records the non-zero exit.Retry once. If it persists, surface to the user and report via the Actor's Issues tab with the run id. Never assume data was produced — re-check the dataset / OUTPUT on retry.

Informational screening only — not legal advice. None of these codes is a trademark verdict. A clear / caution / high-risk result is carried in OUTPUT.records[].brandReadiness, not in the error channel. See FAQ for the legal boundary.


FAQ

Why does the same name sometimes get a different risk score per jurisdiction? Each jurisdiction is screened against its own curated mark dataset, so a name can collide with a real mark in one jurisdiction's sample and not another's. This is expected, not a bug.

What does marksScreened tell me, and why does a clear come with a number? marksScreened is the count of in-scope marks actually scored for a verdict (after the Nice-class filter). A clear over 3 marks is a much weaker signal than a clear over 150, so every verdict carries its denominator. Read clear as "no collision found in the screened seed," not as "trademark-free" — a real registry may hold a conflicting mark that isn't in the curated sample.

What does attorneyReview.recommended: true actually get me? Nothing beyond the message itself — it's a flag, not a referral. There is no attorney network, fee, or law-firm relationship behind it; it's the same "get clearance" advice as the recommendation field, surfaced as a structured boolean an agent can branch on.

Why is niceClassesSource sometimes "inferred" even though I set industry? niceClassesSource is "inferred" whenever niceClasses was left empty — the engine then derives classes from a curated keyword table keyed on industry (e.g. "fintech" → classes 9, 36, 42). Set niceClasses explicitly if you want "user" provenance and tighter scoping.

Will the same positioning always generate the same names? No. LLM generation is non-deterministic — the same input can produce different candidates across runs. The trademark/domain verdicts for a given generated name are deterministic.

Can a domain marked available be taken later? Yes. RDAP results are a point-in-time snapshot. Re-confirm before relying on it.

Is my input data sent anywhere? In generate mode, positioning/industry/tone/etc. are sent to a third-party LLM provider (via OpenRouter) to generate candidates. Screen mode sends nothing externally except the RDAP domain probes (no credentials, no PII).


Known limitations

LimitationWhat to expect
Curated seed data, not full registriesFamous-mark collision screening only — a clear verdict means no collision found in the curated seed, not "trademark-free". A name can still conflict with a real mark not in the sample. Weight a clear by the per-jurisdiction marksScreened count.
Non-deterministic generationThe same positioning may produce different candidates on different runs.
Point-in-time domain availabilityA TLD marked available may be claimed before you register it.
Max 20 names/candidates per runHard cap; larger batches require multiple runs.
Non-Latin names are not screenableA name that normalizes to an empty core is surfaced as not_screened — reason name_not_latin_screenable when its letters are all non-Latin (CJK / Cyrillic), or name_has_no_distinctive_core when it carries no script at all (punctuation / emoji only). Never scored as a false clear, never billed.
Lookalike-script names are not screenableA name mixing Latin with a lookalike script (Cyrillic, Greek, Armenian, Cherokee, fullwidth or mathematical letterforms — e.g. Gоogle with a Cyrillic o, or Google with a fullwidth G) is surfaced as not_screened with reason confusable_script. Normalizing it would silently screen a different name, so it is never scored and never billed.
No social-handle checkDomain availability is checked; GitHub/X/Twitch/etc. handle availability is not (see the sibling AI Username Generator Actor).

Data & privacy

  • Generate mode only: positioning, industry, tone, techniques, mustInclude, and avoid are sent to a third-party LLM provider (via OpenRouter) to generate candidates. Do not include personal data you don't want shared with an LLM provider.
  • Domain checks are unauthenticated — no credentials are sent to any registry, and no raw external response bodies are stored in your dataset or logs.
  • Data retention: datasets are retained per your Apify account settings. Delete the run to erase its outputs.

Develop

pnpm install
pnpm test # unit tests (no network — RDAP/LLM sources are injected)
pnpm type-check
pnpm lint

RDAP environment variables (optional)

Copy .env.example to .env and uncomment to override:

variabledefaulteffect
RDAP_ENABLEDtrueset to false to skip the network calls
RDAP_TIMEOUT_MS5000per-request HTTP timeout
RDAP_CONCURRENCY4max simultaneous RDAP probes

Generation environment variables

Operator-side, only read in generate mode (positioning set) and only when the run does not supply its own llmApiKey (see Bring-your-own LLM). On Apify, set these as secret environment variables (Console → Settings → Environment variables) — they are injected at run time and never baked into the build image or exposed to users.

variabledefaulteffect
OPENROUTER_API_KEYrequired for generate mode when no user llmApiKey is supplied; the operator's LLM key.
OPENROUTER_BASE_URLOpenRouter's chat-completions endpointmust be HTTPS (plain HTTP allowed for localhost only). Ignored for llmProvider: "anthropic" runs.
LLM_PRIMARY_MODELdeepseek/deepseek-chatprimary generation model. A user-supplied llmModel overrides both primary and fallback.
LLM_FALLBACK_MODELopenai/gpt-4o-minifallback model on primary failure/timeout/malformed JSON.
LLM_TIMEOUT_MS8000per-request timeout for both models.

Contributing

Source: github.com/m-raphael/brand-name-ip-screener. Contributions are welcome — see ./CONTRIBUTING.md for setup, the test-first workflow, the schema-coordination rules, and the hard invariants ("never a false clear", the UPL boundary, no referral/fee logic in this Actor). The repo runs CI (type-check, lint, network-free tests, build) on every pull request.

Seed-data provenance, the third-party-trademark notice, and coverage limits are documented in ./DATA-SOURCES.md — read that before relying on a verdict, and use it to file a correction if a seed entry is wrong.

Security

Found a security issue — especially anything touching key custody (the operator OPENROUTER_API_KEY must never reach a user-supplied endpoint)? Do not open a public issue; see ./SECURITY.md for the private reporting channel and the bug classes that matter most here.


Support

Found a bug or want a jurisdiction added? Open an issue on the Actor's Issues tab in the Apify Console — that is the primary support channel — or on GitHub. Security reports go through ./SECURITY.md, not public issues.