Trademark Search (TMview API)
Checks a name against the TMview database via its public JSON API
(tmdn.org/tmview). One query covers EUIPO (EM) plus national offices
(Germany DE, Austria AT, Switzerland CH, WIPO WO, and all EU offices).
No agent-browser, no API key — just curl + jq (1.6 or newer). The API needs HTTP/1.1
and a primed session cookie; the script handles both. If jq is missing or too old the
script exits 127 with an install hint.
Usage
scripts/tmview-search.sh "<term>" [offices] # path relative to this skill dir
scripts/tmview-search.sh "tenderling" # EUIPO only (default) -> clear
scripts/tmview-search.sh "dendu" -o DACH # EUIPO + DE + AT + CH
scripts/tmview-search.sh "tendena" -o EM,DE # custom office list
scripts/tmview-search.sh "acme" -o ALL # every office in TMview
scripts/tmview-search.sh "nike" -r 0 # heavily taken, print all rows
scripts/tmview-search.sh "acme" -c 25,35 -p 5 # apparel/retail classes, 500 marks
scripts/tmview-search.sh "acme" --json # merged raw JSON for further processing
| Option |
Meaning |
-o, --offices |
EM (EUIPO, default) · DACH = EM,DE,AT,CH · EU = EM · ALL = no filter · or a comma list of office codes e.g. EM,DE,WO |
-c, --classes |
Nice classes that count as a conflict (default 9,35,42 = software/SaaS) |
-p, --pages |
result pages to fetch, 100 marks each (default 3) |
-r, --rows |
table rows to print, 0 = all (default 25) |
-j, --json |
merged raw JSON instead of the report |
The legacy positional form "<term>" DACH still works.
Output
- Total matches (contains) — every mark whose name contains the term
(catches similar marks, not just identical ones), plus how many were analysed.
- A table sorted most-relevant-first:
mark name · [office] · status · Nice classes · owner,
where » marks an identical name and × a dead status.
- Verdict, derived automatically:
✅ clear — no mark contains the term.
✅ likely usable — hits exist but none is identical (all longer/similar words).
⚠️ dead identical — identical mark(s) exist but all are expired/ended.
⚠️ live, other classes — identical live mark(s) outside the conflict classes.
⛔ conflict — an identical, live mark exists in a conflict class (9/35/42 by default).
Exit codes: 0 report produced · 2 API unreachable/unparseable · 3 office filter invalid
(see below) · 127 missing curl/jq.
Accuracy notes
- Identical is judged on a normalised name: lowercase, punctuation and spaces removed,
so
DEN-DU, den du and dendu all count as identical.
- Live uses a dead-status deny list (expired, ended, withdrawn, refused, cancelled,
invalid, surrendered, lapsed, …). Unknown statuses count as live, so the verdict errs
toward caution.
- The API only matches "contains", so all identical/class analysis happens locally over the
fetched pages — raise
--pages for very common terms (the header tells you when results
were truncated).
- TMview silently returns zero results for invalid office codes instead of an error.
The script detects this with a control query and exits
3 rather than reporting a false
"clear".
Interpreting results
For SaaS/software the relevant Nice classes are 9 (software), 42 (SaaS/tech
services), 35 (business/advertising). When judging a hit, weigh:
- Identical vs similar —
DENDUR ≠ DENDU; substring hits like ADDENDUM,
CLOUDENDURE are usually irrelevant.
- Status —
Registered/Filed/Opposition = live; Expired/Ended/
Withdrawn/Refused = dead (much lower risk).
- Class overlap — an identical live mark in class 9/35/42 is the real blocker;
the same word in apparel (25) or cosmetics (3) is usually fine.
The script's ⛔ verdict fires only when all three line up (identical + live +
software class). Always still eyeball the table.
Related
Naming a product end-to-end? name-availability combines
this check with domain availability across TLDs and produces a per-candidate verdict table.
Caveat
Indicator only, not legal advice. TMview reflects office data with some lag and
the API does phonetic/fuzzy matching less aggressively than a professional clearance.
Before filing or launching, have a trademark attorney run a full search (including
phonetic and similar-mark analysis) and confirm the live national registers.
1---2name: trademark-search3description: Search EU & national trademarks for a name via the public TMview API (EUIPO + DE/AT/CH/WIPO). Use when checking whether a brand/product/company name is free of conflicting trademarks before adopting it. Returns matching marks with their Nice classes, status and owner, plus an exact-match / software-class conflict verdict. Triggers include "search trademarks", "is X trademarked", "EUIPO search", "TM search", "check the trademark", "is this brand name taken".4---56# Trademark Search (TMview API)78Checks a name against the **TMview** database via its public JSON API9(`tmdn.org/tmview`). One query covers **EUIPO (EM)** plus **national offices**10(Germany DE, Austria AT, Switzerland CH, WIPO WO, and all EU offices).1112No agent-browser, no API key — just `curl` + `jq` (1.6 or newer). The API needs HTTP/1.113and a primed session cookie; the script handles both. If `jq` is missing or too old the14script exits `127` with an install hint.1516## Usage1718```bash19scripts/tmview-search.sh "<term>" [offices] # path relative to this skill dir2021scripts/tmview-search.sh "tenderling" # EUIPO only (default) -> clear22scripts/tmview-search.sh "dendu" -o DACH # EUIPO + DE + AT + CH23scripts/tmview-search.sh "tendena" -o EM,DE # custom office list24scripts/tmview-search.sh "acme" -o ALL # every office in TMview25scripts/tmview-search.sh "nike" -r 0 # heavily taken, print all rows26scripts/tmview-search.sh "acme" -c 25,35 -p 5 # apparel/retail classes, 500 marks27scripts/tmview-search.sh "acme" --json # merged raw JSON for further processing28```2930| Option | Meaning |31|---|---|32| `-o, --offices` | `EM` (EUIPO, default) · `DACH` = EM,DE,AT,CH · `EU` = EM · `ALL` = no filter · or a comma list of [office codes](https://www.tmdn.org/tmview/) e.g. `EM,DE,WO` |33| `-c, --classes` | Nice classes that count as a conflict (default `9,35,42` = software/SaaS) |34| `-p, --pages` | result pages to fetch, 100 marks each (default 3) |35| `-r, --rows` | table rows to print, `0` = all (default 25) |36| `-j, --json` | merged raw JSON instead of the report |3738The legacy positional form `"<term>" DACH` still works.3940## Output4142- **Total matches (contains)** — every mark whose name *contains* the term43 (catches similar marks, not just identical ones), plus how many were analysed.44- A table sorted most-relevant-first: `mark name · [office] · status · Nice classes · owner`,45 where `»` marks an identical name and `×` a dead status.46- **Verdict**, derived automatically:47 - `✅ clear` — no mark contains the term.48 - `✅ likely usable` — hits exist but none is identical (all longer/similar words).49 - `⚠️ dead identical` — identical mark(s) exist but all are expired/ended.50 - `⚠️ live, other classes` — identical live mark(s) outside the conflict classes.51 - `⛔ conflict` — an identical, **live** mark exists in a conflict class (9/35/42 by default).5253Exit codes: `0` report produced · `2` API unreachable/unparseable · `3` office filter invalid54(see below) · `127` missing `curl`/`jq`.5556## Accuracy notes5758- **Identical** is judged on a normalised name: lowercase, punctuation and spaces removed,59 so `DEN-DU`, `den du` and `dendu` all count as identical.60- **Live** uses a dead-status deny list (expired, ended, withdrawn, refused, cancelled,61 invalid, surrendered, lapsed, …). Unknown statuses count as *live*, so the verdict errs62 toward caution.63- The API only matches "contains", so all identical/class analysis happens locally over the64 fetched pages — raise `--pages` for very common terms (the header tells you when results65 were truncated).66- TMview silently returns **zero results for invalid office codes** instead of an error.67 The script detects this with a control query and exits `3` rather than reporting a false68 "clear".6970## Interpreting results7172For SaaS/software the relevant **Nice classes are 9 (software), 42 (SaaS/tech73services), 35 (business/advertising)**. When judging a hit, weigh:74751. **Identical vs similar** — `DENDUR` ≠ `DENDU`; substring hits like `ADDENDUM`,76 `CLOUDENDURE` are usually irrelevant.772. **Status** — `Registered`/`Filed`/`Opposition` = live; `Expired`/`Ended`/78 `Withdrawn`/`Refused` = dead (much lower risk).793. **Class overlap** — an identical live mark in class 9/35/42 is the real blocker;80 the same word in apparel (25) or cosmetics (3) is usually fine.8182The script's `⛔` verdict fires only when all three line up (identical + live +83software class). Always still eyeball the table.8485## Related8687Naming a product end-to-end? [`name-availability`](../name-availability/SKILL.md) combines88this check with domain availability across TLDs and produces a per-candidate verdict table.8990## Caveat9192Indicator only, **not legal advice.** TMview reflects office data with some lag and93the API does phonetic/fuzzy matching less aggressively than a professional clearance.94Before filing or launching, have a trademark attorney run a full search (including95phonetic and similar-mark analysis) and confirm the live national registers.