@biggora/claude-plugins 1.1.1 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/.claude/settings.local.json +3 -1
  2. package/README.md +24 -17
  3. package/package.json +1 -1
  4. package/registry/registry.json +319 -244
  5. package/specs/coding.md +24 -0
  6. package/specs/pod.md +2 -0
  7. package/src/skills/captcha/README.md +221 -0
  8. package/src/skills/captcha/SKILL.md +355 -0
  9. package/src/skills/captcha/references/captcha-types.md +254 -0
  10. package/src/skills/captcha/references/services.md +172 -0
  11. package/src/skills/captcha/references/stealth.md +238 -0
  12. package/src/skills/captcha/scripts/solve_captcha.py +323 -0
  13. package/src/skills/captcha/scripts/solve_image_grid.py +350 -0
  14. package/src/skills/codex-cli/SKILL.md +21 -11
  15. package/src/skills/gemini-cli/SKILL.md +27 -13
  16. package/src/skills/gemini-cli/references/commands.md +21 -14
  17. package/src/skills/gemini-cli/references/configuration.md +23 -18
  18. package/src/skills/gemini-cli/references/headless-and-scripting.md +7 -17
  19. package/src/skills/gemini-cli/references/mcp-and-extensions.md +12 -6
  20. package/src/skills/google-merchant-api/SKILL.md +581 -0
  21. package/src/skills/google-merchant-api/references/accounts.md +247 -0
  22. package/src/skills/google-merchant-api/references/content-api-legacy.md +216 -0
  23. package/src/skills/google-merchant-api/references/datasources.md +233 -0
  24. package/src/skills/google-merchant-api/references/inventories.md +201 -0
  25. package/src/skills/google-merchant-api/references/migration.md +267 -0
  26. package/src/skills/google-merchant-api/references/products.md +316 -0
  27. package/src/skills/google-merchant-api/references/promotions.md +201 -0
  28. package/src/skills/google-merchant-api/references/reports.md +240 -0
  29. package/src/skills/lv-aggregators-api/SKILL.md +113 -0
  30. package/src/skills/lv-aggregators-api/references/integration-guide.md +368 -0
  31. package/src/skills/lv-aggregators-api/references/kurpirkt.md +103 -0
  32. package/src/skills/lv-aggregators-api/references/salidzini.md +122 -0
  33. package/src/skills/notebook-lm/SKILL.md +1 -1
  34. package/src/skills/screen-recording/SKILL.md +243 -213
  35. package/src/skills/screen-recording/references/design-patterns.md +4 -2
  36. package/src/skills/screen-recording/references/ffmpeg-recording.md +473 -0
  37. package/src/skills/screen-recording/references/{approach1-programmatic.md → programmatic-generation.md} +45 -22
  38. package/src/skills/screen-recording/references/python-fallback.md +222 -0
  39. package/src/skills/tailwindcss-best-practices/SKILL.md +180 -0
  40. package/src/skills/tailwindcss-best-practices/references/best-practices-utility-patterns.md +87 -0
  41. package/src/skills/tailwindcss-best-practices/references/core-installation.md +109 -0
  42. package/src/skills/tailwindcss-best-practices/references/core-preflight.md +200 -0
  43. package/src/skills/tailwindcss-best-practices/references/core-responsive.md +163 -0
  44. package/src/skills/tailwindcss-best-practices/references/core-source-detection.md +114 -0
  45. package/src/skills/tailwindcss-best-practices/references/core-theme.md +108 -0
  46. package/src/skills/tailwindcss-best-practices/references/core-utility-classes.md +59 -0
  47. package/src/skills/tailwindcss-best-practices/references/core-variants.md +204 -0
  48. package/src/skills/tailwindcss-best-practices/references/effects-form-controls.md +76 -0
  49. package/src/skills/tailwindcss-best-practices/references/effects-mask.md +91 -0
  50. package/src/skills/tailwindcss-best-practices/references/effects-scroll-snap.md +59 -0
  51. package/src/skills/tailwindcss-best-practices/references/effects-text-shadow.md +78 -0
  52. package/src/skills/tailwindcss-best-practices/references/effects-transition-animation.md +80 -0
  53. package/src/skills/tailwindcss-best-practices/references/effects-visibility-interactivity.md +82 -0
  54. package/src/skills/tailwindcss-best-practices/references/features-content-detection.md +175 -0
  55. package/src/skills/tailwindcss-best-practices/references/features-custom-styles.md +203 -0
  56. package/src/skills/tailwindcss-best-practices/references/features-dark-mode.md +137 -0
  57. package/src/skills/tailwindcss-best-practices/references/features-functions-directives.md +241 -0
  58. package/src/skills/tailwindcss-best-practices/references/features-upgrade.md +160 -0
  59. package/src/skills/tailwindcss-best-practices/references/layout-aspect-ratio.md +39 -0
  60. package/src/skills/tailwindcss-best-practices/references/layout-columns.md +80 -0
  61. package/src/skills/tailwindcss-best-practices/references/layout-display.md +110 -0
  62. package/src/skills/tailwindcss-best-practices/references/layout-flexbox.md +112 -0
  63. package/src/skills/tailwindcss-best-practices/references/layout-grid.md +87 -0
  64. package/src/skills/tailwindcss-best-practices/references/layout-height.md +97 -0
  65. package/src/skills/tailwindcss-best-practices/references/layout-inset.md +103 -0
  66. package/src/skills/tailwindcss-best-practices/references/layout-logical-properties.md +92 -0
  67. package/src/skills/tailwindcss-best-practices/references/layout-margin.md +126 -0
  68. package/src/skills/tailwindcss-best-practices/references/layout-min-max-sizing.md +63 -0
  69. package/src/skills/tailwindcss-best-practices/references/layout-object-fit-position.md +64 -0
  70. package/src/skills/tailwindcss-best-practices/references/layout-overflow.md +57 -0
  71. package/src/skills/tailwindcss-best-practices/references/layout-padding.md +77 -0
  72. package/src/skills/tailwindcss-best-practices/references/layout-position.md +85 -0
  73. package/src/skills/tailwindcss-best-practices/references/layout-tables.md +67 -0
  74. package/src/skills/tailwindcss-best-practices/references/layout-width.md +102 -0
  75. package/src/skills/tailwindcss-best-practices/references/transform-base.md +68 -0
  76. package/src/skills/tailwindcss-best-practices/references/transform-rotate.md +70 -0
  77. package/src/skills/tailwindcss-best-practices/references/transform-scale.md +83 -0
  78. package/src/skills/tailwindcss-best-practices/references/transform-skew.md +62 -0
  79. package/src/skills/tailwindcss-best-practices/references/transform-translate.md +77 -0
  80. package/src/skills/tailwindcss-best-practices/references/typography-font-text.md +142 -0
  81. package/src/skills/tailwindcss-best-practices/references/typography-list-style.md +65 -0
  82. package/src/skills/tailwindcss-best-practices/references/typography-text-align.md +60 -0
  83. package/src/skills/tailwindcss-best-practices/references/visual-background.md +76 -0
  84. package/src/skills/tailwindcss-best-practices/references/visual-border.md +108 -0
  85. package/src/skills/tailwindcss-best-practices/references/visual-effects.md +111 -0
  86. package/src/skills/tailwindcss-best-practices/references/visual-svg.md +82 -0
  87. package/src/skills/test-mobile-app/SKILL.md +11 -6
  88. package/src/skills/test-mobile-app/scripts/analyze_apk.py +15 -4
  89. package/src/skills/test-mobile-app/scripts/check_environment.py +5 -5
  90. package/src/skills/test-mobile-app/scripts/run_tests.py +1 -1
  91. package/src/skills/test-web-ui/SKILL.md +264 -84
  92. package/src/skills/test-web-ui/scripts/discover.py +25 -12
  93. package/src/skills/test-web-ui/scripts/run_tests.py +3 -2
  94. package/src/skills/tm-search/SKILL.md +242 -106
  95. package/src/skills/tm-search/references/scraping-fallback.md +60 -95
  96. package/src/skills/tm-search/scripts/tm_search.py +453 -375
  97. package/src/skills/vite-best-practices/SKILL.md +115 -0
  98. package/src/skills/vite-best-practices/references/build-and-ssr.md +255 -0
  99. package/src/skills/vite-best-practices/references/core-config.md +231 -0
  100. package/src/skills/vite-best-practices/references/core-features.md +222 -0
  101. package/src/skills/vite-best-practices/references/core-plugin-api.md +294 -0
  102. package/src/skills/vite-best-practices/references/environment-api.md +108 -0
  103. package/src/skills/vite-best-practices/references/rolldown-migration.md +242 -0
  104. package/src/skills/screen-recording/references/approach2-xvfb.md +0 -232
@@ -16,123 +16,283 @@ description: >
16
16
 
17
17
  This skill enables an agent to search, validate, and analyze US trademarks via USPTO APIs.
18
18
 
19
- ## API Overview
19
+ ## Important: API Access Reality
20
+
21
+ The USPTO trademark search system (`tmsearch.uspto.gov`) uses **AWS WAF bot protection** on its
22
+ Elasticsearch search backend. Direct keyword search via HTTP is **not possible** without browser
23
+ automation. However, the **TSDR details API** (case lookup by serial number) works without
24
+ authentication and returns JSON.
25
+
26
+ For **keyword search**, use one of these approaches:
27
+ 1. **Playwright/browser automation** — drive the tmsearch.uspto.gov web UI (most reliable)
28
+ 2. **Third-party API** — RapidAPI USPTO wrapper (requires API key, simpler to use)
20
29
 
21
- There are **two main API approaches** choose based on needs:
30
+ For **case status lookup by serial number**, the built-in TSDR API works directly.
22
31
 
23
- | Use Case | API |
32
+ ## API Overview
33
+
34
+ | Use Case | Approach |
24
35
  |---|---|
25
- | Keyword/name text search, availability check | **tmsearch.uspto.gov** (web backend) |
26
- | Status lookup by serial/registration number | **tsdrapi.uspto.gov** (official TSDR API) |
27
- | Batch/programmatic word validation | **tmsearch.uspto.gov** or RapidAPI wrapper |
36
+ | Keyword/name text search | Browser automation on tmsearch.uspto.gov **or** RapidAPI |
37
+ | Case status by serial number | TSDR Details API (no auth, JSON) |
38
+ | Batch keyword validation | Browser automation + delays **or** RapidAPI |
39
+ | Case documents / images | TSDR API (requires API key since Oct 2024) |
28
40
 
29
41
  ---
30
42
 
31
- ## API 1: tmsearch.uspto.gov (New Trademark SearchNo API key required)
43
+ ## API 1: TSDR Details API (No auth requiredJSON)
32
44
 
33
- The USPTO replaced TESS in November 2023 with a new search system at `https://tmsearch.uspto.gov`.
34
- This is a **web application** but its backend can be called directly.
45
+ Look up trademark case details **by serial number**. This endpoint is hosted on the tmsearch
46
+ site and returns JSON without authentication.
35
47
 
36
- ### Search Endpoint
48
+ ### Endpoint
37
49
 
38
50
  ```
39
- POST https://tmsearch.uspto.gov/search/keyword
40
- Content-Type: application/json
51
+ GET https://tmsearch.uspto.gov/tsdr-api-v1-0-0/tsdr-api?serialNumber={SERIAL_NUMBER}
41
52
  ```
42
53
 
43
- **Request body:**
44
- ```json
45
- {
46
- "keyword": "APPLE",
47
- "searchType": "1",
48
- "statusType": "A",
49
- "pluralVariants": false,
50
- "start": 0,
51
- "rows": 25
52
- }
53
- ```
54
-
55
- **Parameters:**
56
- - `keyword` — the word/phrase to search (required)
57
- - `searchType` — `"1"` = basic keyword, `"2"` = design code, `"3"` = owner name
58
- - `statusType` — `"A"` = active/live only, `"D"` = dead only, `""` = all
59
- - `pluralVariants` — `true` to include plural variations
60
- - `start` — pagination offset (0-indexed)
61
- - `rows` — results per page (max 500)
62
-
63
- ### Alternative: GET search
54
+ Serial numbers are 8 digits (no dashes). Example:
64
55
 
65
- ```
66
- GET https://tmsearch.uspto.gov/search/keyword?keyword=APPLE&statusType=A&rows=25
56
+ ```bash
57
+ curl -s "https://tmsearch.uspto.gov/tsdr-api-v1-0-0/tsdr-api?serialNumber=78787878" \
58
+ -H "Accept: application/json"
67
59
  ```
68
60
 
69
- ### Response Fields
61
+ ### Response Structure
70
62
 
71
63
  ```json
72
64
  {
73
- "totalFound": 1247,
74
- "trademarks": [
65
+ "metadata": {
66
+ "caseStatus": "Abandoned because the applicant failed to respond...",
67
+ "statusDate": "2007-09-25",
68
+ "owners": [
69
+ {
70
+ "ipInfo": {
71
+ "name": "OWNER NAME",
72
+ "legalEntity": "3",
73
+ "contactAddress": {
74
+ "mailingAddresses": [
75
+ {
76
+ "cityName": "City",
77
+ "geographicRegionName": "STATE",
78
+ "postalCode": "12345",
79
+ "countryName": "UNITED STATES OF AMERICA"
80
+ }
81
+ ]
82
+ },
83
+ "citizenship": {
84
+ "countryName": "UNITED STATES OF AMERICA",
85
+ "geographicRegionName": "STATE"
86
+ }
87
+ }
88
+ }
89
+ ],
90
+ "attorney": {
91
+ "ipInfo": { "name": "Attorney Name" }
92
+ },
93
+ "correspondent": {
94
+ "ipInfo": {
95
+ "name": "Correspondent Name",
96
+ "contactAddress": { "mailingAddresses": [...], "electronicAddresses": [...] }
97
+ }
98
+ },
99
+ "markDetails": {
100
+ "isStandardCharClaimed": false
101
+ },
102
+ "tm5Status": {
103
+ "tm5StatusDescription": "...",
104
+ "tm5StatusCode": "10",
105
+ "tm5StatusDescriptor": "DEAD/APPLICATION/Refused/Dismissed or Invalidated",
106
+ "tm5LiveDead": "dead"
107
+ },
108
+ "classes": [
109
+ { "classNumber": "009", "firstUseAnywhereDate": null, "firstUseInCommerceDate": null }
110
+ ],
111
+ "docketNumber": "..."
112
+ },
113
+ "maintenance": {},
114
+ "prosecutionHistory": [
75
115
  {
76
- "serialNumber": "75123456",
77
- "registrationNumber": "2345678",
78
- "wordMark": "APPLE",
79
- "status": "Live/Registered",
80
- "statusCode": "A",
81
- "filingDate": "1997-03-15",
82
- "registrationDate": "1999-08-17",
83
- "owner": "Apple Inc.",
84
- "ownerAddress": "Cupertino, CALIFORNIA, UNITED STATES",
85
- "internationalClassification": ["009", "042"],
86
- "goodsServices": "Computers, computer software...",
87
- "attorney": "...",
88
- "markDrawingCode": "4"
116
+ "historyDate": "2026-03-06",
117
+ "historyDescription": "Amended Drawing",
118
+ "documentId": "https://tsdr.uspto.gov/documentviewer?caseId=sn78787878&docId=..."
89
119
  }
90
- ]
120
+ ],
121
+ "assignments": [...],
122
+ "proceedings": [...],
123
+ "international": {}
91
124
  }
92
125
  ```
93
126
 
94
- > **Note:** The tmsearch.uspto.gov backend API is not officially documented. If the above endpoint
95
- > returns errors, fall back to scraping `https://tmsearch.uspto.gov/search/search-information` or
96
- > use the TSDR API below. See `references/scraping-fallback.md` for the web scraping approach.
127
+ ### Key Response Fields
97
128
 
98
- ---
129
+ | Path | Description |
130
+ |---|---|
131
+ | `metadata.caseStatus` | Human-readable current status |
132
+ | `metadata.statusDate` | Date of last status change |
133
+ | `metadata.owners[].ipInfo.name` | Owner/applicant name |
134
+ | `metadata.owners[].ipInfo.contactAddress` | Owner address |
135
+ | `metadata.attorney.ipInfo.name` | Attorney of record |
136
+ | `metadata.tm5Status.tm5LiveDead` | `"live"` or `"dead"` |
137
+ | `metadata.tm5Status.tm5StatusDescriptor` | Structured status (e.g., `"LIVE/REGISTRATION/Registered"`) |
138
+ | `metadata.classes[].classNumber` | Nice Classification codes |
139
+ | `metadata.markDetails.isStandardCharClaimed` | Whether it's a standard character mark |
140
+ | `prosecutionHistory[]` | Timeline of case events with document links |
141
+
142
+ > **Note:** This API does NOT return the word mark text itself. To get the mark text, you need
143
+ > the keyword search approach (browser automation or RapidAPI).
99
144
 
100
- ## API 2: TSDR API (Official — requires API key for bulk use)
145
+ ---
101
146
 
102
- Looks up trademark **by serial number or registration number**. Returns full case status, documents.
147
+ ## API 2: TSDR Bulk API (Requires API key XML)
103
148
 
104
- **Base URL:** `https://tsdrapi.uspto.gov/ts/cd/`
149
+ The original TSDR API at `tsdrapi.uspto.gov` now **requires an API key for all requests** (changed
150
+ October 2024). Register at https://account.uspto.gov/api-manager/.
105
151
 
106
- ### Key Endpoints
152
+ ### Endpoints
107
153
 
108
154
  ```bash
109
- # Case status by serial number (HTML)
110
- GET https://tsdrapi.uspto.gov/ts/cd/casestatus/sn{SERIAL_NUMBER}/content.html
111
-
112
- # Case status as XML (machine-readable)
155
+ # Case status as XML (requires API key)
113
156
  GET https://tsdrapi.uspto.gov/ts/cd/casestatus/sn{SERIAL_NUMBER}/info.xml
157
+ Header: USPTO-API-KEY: YOUR_KEY
158
+
159
+ # Case status as HTML
160
+ GET https://tsdrapi.uspto.gov/ts/cd/casestatus/sn{SERIAL_NUMBER}/content.html
161
+ Header: USPTO-API-KEY: YOUR_KEY
114
162
 
115
- # Case status by registration number
163
+ # By registration number
116
164
  GET https://tsdrapi.uspto.gov/ts/cd/casestatus/rn{REG_NUMBER}/info.xml
117
165
 
118
- # Case documents as PDF bundle
166
+ # Case documents PDF bundle
119
167
  GET https://tsdrapi.uspto.gov/ts/cd/casedocs/bundle.pdf?sn={SERIAL_NUMBER}
120
168
 
121
169
  # Raw trademark image
122
170
  GET https://tsdrapi.uspto.gov/ts/cd/rawImage/{SERIAL_NUMBER}
123
171
  ```
124
172
 
125
- ### API Key (required for bulk/automated use)
173
+ Rate limit: **60 requests/minute per API key**.
174
+
175
+ ---
176
+
177
+ ## Keyword Search via Browser Automation (Recommended)
178
+
179
+ Since the tmsearch.uspto.gov search backend is protected by AWS WAF, use Playwright to drive
180
+ the web UI and intercept API responses.
181
+
182
+ **Important:** The AWS WAF bot detection is non-deterministic — headless browsers are blocked
183
+ intermittently. Use anti-detection settings and retries. Even with these, keyword search may
184
+ fail occasionally. The RapidAPI wrapper (below) is more reliable if you need consistent results.
185
+
186
+ ```python
187
+ from playwright.sync_api import sync_playwright
188
+
189
+ def search_trademark(keyword: str, max_results: int = 25) -> dict:
190
+ """Search USPTO trademarks by keyword using browser automation."""
191
+ results = {"totalFound": 0, "trademarks": []}
192
+
193
+ with sync_playwright() as p:
194
+ # Anti-detection settings to bypass AWS WAF
195
+ browser = p.chromium.launch(
196
+ headless=True,
197
+ args=["--disable-blink-features=AutomationControlled"],
198
+ )
199
+ context = browser.new_context(
200
+ user_agent=(
201
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
202
+ "AppleWebKit/537.36 (KHTML, like Gecko) "
203
+ "Chrome/120.0.0.0 Safari/537.36"
204
+ ),
205
+ viewport={"width": 1920, "height": 1080},
206
+ )
207
+ page = context.new_page()
208
+ page.add_init_script(
209
+ 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})'
210
+ )
211
+
212
+ # Intercept the Elasticsearch API responses
213
+ def handle_response(response):
214
+ if "prod-stage" in response.url and response.status == 200:
215
+ try:
216
+ data = response.json()
217
+ if isinstance(data, dict) and "hits" in data:
218
+ hits = data.get("hits", {})
219
+ total = hits.get("total", {})
220
+ results["totalFound"] = total.get("value", 0) if isinstance(total, dict) else total
221
+ for hit in hits.get("hits", [])[:max_results]:
222
+ results["trademarks"].append(hit.get("_source", {}))
223
+ except Exception:
224
+ pass
225
+
226
+ page.on("response", handle_response)
227
+ page.goto("https://tmsearch.uspto.gov/search/search-information", timeout=30000)
228
+ page.wait_for_load_state("networkidle")
229
+ page.wait_for_timeout(2000) # Wait for WAF challenge to resolve
230
+
231
+ # Type keyword and submit
232
+ search_input = page.locator('input[type="text"]').first
233
+ search_input.fill(keyword.upper(), timeout=10000)
234
+ search_input.press("Enter")
235
+
236
+ # Wait for results (longer wait needed for WAF + async results)
237
+ page.wait_for_timeout(6000)
238
+
239
+ browser.close()
240
+
241
+ return results
242
+ ```
243
+
244
+ ### Install Playwright
245
+
246
+ ```bash
247
+ pip install playwright
248
+ playwright install chromium
249
+ ```
250
+
251
+ ---
252
+
253
+ ## Keyword Search via RapidAPI (Alternative — requires API key)
254
+
255
+ If browser automation is not practical, the RapidAPI unofficial USPTO wrapper provides reliable
256
+ keyword search.
126
257
 
127
- - Register at: https://account.uspto.gov/api-manager/
128
- - Add key as header: `USPTO-API-KEY: YOUR_KEY_HERE`
129
- - Rate limit: **60 requests/minute per API key**
258
+ **Sign up:** https://rapidapi.com/pentium10/api/uspto-trademark
130
259
 
131
260
  ```bash
132
- curl -H "USPTO-API-KEY: YOUR_KEY" \
133
- "https://tsdrapi.uspto.gov/ts/cd/casestatus/sn78787878/info.xml"
261
+ # Keyword search (active marks)
262
+ curl "https://uspto-trademark.p.rapidapi.com/v1/trademarkSearch/APPLE/active" \
263
+ -H "x-rapidapi-host: uspto-trademark.p.rapidapi.com" \
264
+ -H "x-rapidapi-key: YOUR_RAPIDAPI_KEY"
265
+
266
+ # Availability check
267
+ curl "https://uspto-trademark.p.rapidapi.com/v1/trademarkAvailable/CLOUDPEAK" \
268
+ -H "x-rapidapi-host: uspto-trademark.p.rapidapi.com" \
269
+ -H "x-rapidapi-key: YOUR_RAPIDAPI_KEY"
270
+
271
+ # Search by owner
272
+ curl "https://uspto-trademark.p.rapidapi.com/v1/ownerSearch/Apple%20Inc/" \
273
+ -H "x-rapidapi-host: uspto-trademark.p.rapidapi.com" \
274
+ -H "x-rapidapi-key: YOUR_RAPIDAPI_KEY"
275
+
276
+ # Lookup by serial number
277
+ curl "https://uspto-trademark.p.rapidapi.com/v1/serialSearch/78787878" \
278
+ -H "x-rapidapi-host: uspto-trademark.p.rapidapi.com" \
279
+ -H "x-rapidapi-key: YOUR_RAPIDAPI_KEY"
280
+
281
+ # Batch search (POST)
282
+ curl -X POST "https://uspto-trademark.p.rapidapi.com/v1/batchTrademarkSearch" \
283
+ -H "x-rapidapi-host: uspto-trademark.p.rapidapi.com" \
284
+ -H "x-rapidapi-key: YOUR_RAPIDAPI_KEY" \
285
+ -H "Content-Type: application/json" \
286
+ -d '{"keywords": ["CLOUDPEAK", "SKYBRIDGE", "NEONPULSE"]}'
134
287
  ```
135
288
 
289
+ RapidAPI endpoints:
290
+ - `/v1/trademarkSearch/{keyword}/{status}` — keyword search (`active`, `dead`, or `all`)
291
+ - `/v1/trademarkAvailable/{keyword}` — simple yes/no availability
292
+ - `/v1/ownerSearch/{owner_name}/{postcode}` — search by owner
293
+ - `/v1/serialSearch/{serial_number}` — lookup by serial number
294
+ - `/v1/batchTrademarkSearch` — multiple keywords (POST)
295
+
136
296
  ---
137
297
 
138
298
  ## CLI Tool Implementation (tm-search)
@@ -142,11 +302,11 @@ When building the `tm-search` command-line tool, follow this structure:
142
302
  ### Core Commands
143
303
 
144
304
  ```bash
145
- tm-search keyword <word> # Search by keyword
305
+ tm-search keyword <word> # Search by keyword (uses Playwright)
146
306
  tm-search keyword <word> --status=A # Active trademarks only
147
307
  tm-search keyword <word> --status=D # Dead trademarks only
148
308
  tm-search available <word> # Check if word is available (not registered live)
149
- tm-search status <serial_number> # Lookup by serial number
309
+ tm-search status <serial_number> # Lookup by serial number (uses TSDR API)
150
310
  tm-search batch <word1,word2,...> # Check multiple words
151
311
  tm-search validate <file.txt> # Validate words from a file (one per line)
152
312
  ```
@@ -177,58 +337,34 @@ Top matches:
177
337
  A keyword is considered **AVAILABLE** if there are zero live/active marks with exact OR confusingly
178
338
  similar text. The agent should:
179
339
 
180
- 1. Search exact keyword with `statusType=A`
340
+ 1. Search exact keyword (via Playwright or RapidAPI)
181
341
  2. If results > 0 → **LIKELY REGISTERED** — show matches
182
342
  3. If results == 0 → **LIKELY AVAILABLE** — note this is not legal advice
183
343
  4. Always caveat: suggest professional trademark attorney review before filing
184
344
 
185
- ```python
186
- def check_availability(keyword):
187
- results = search_trademark(keyword, status="A")
188
- if results["totalFound"] == 0:
189
- return "LIKELY AVAILABLE"
190
- else:
191
- return f"LIKELY TAKEN ({results['totalFound']} active marks)"
192
- ```
193
-
194
345
  ---
195
346
 
196
347
  ## Batch Validation
197
348
 
198
- For validating a list of keywords (e.g., from a CSV or text file):
199
-
200
- ```python
201
- words = ["CloudPeak", "SkyBridge", "NeonPulse"]
202
- results = []
203
- for word in words:
204
- r = search_trademark(word.upper(), status="A")
205
- results.append({
206
- "keyword": word,
207
- "status": "AVAILABLE" if r["totalFound"] == 0 else "TAKEN",
208
- "count": r["totalFound"]
209
- })
210
- # Output as table or CSV
211
- ```
212
-
213
- Rate-limit: Add 0.5–1s delay between requests to avoid throttling.
349
+ For validating a list of keywords, add a 2–3 second delay between Playwright searches to avoid
350
+ triggering rate limits. With RapidAPI, 0.5–1s delay is sufficient.
214
351
 
215
352
  ---
216
353
 
217
354
  ## Implementation Notes
218
355
 
219
- - The `tmsearch.uspto.gov` endpoint is a **public government site** — no auth required for search
356
+ - The `tmsearch.uspto.gov` search backend is protected by **AWS WAF** — direct HTTP keyword search does not work
357
+ - The TSDR Details API (`/tsdr-api-v1-0-0/tsdr-api?serialNumber=...`) works without auth and returns JSON
358
+ - The old TSDR XML API (`tsdrapi.uspto.gov`) requires an **API key for all requests** since October 2024
220
359
  - Always **uppercase** keywords before searching (USPTO stores marks in uppercase)
221
- - Include `User-Agent` header to avoid bot detection: `"Mozilla/5.0 (compatible; tm-search/1.0)"`
222
- - For `pluralVariants=true`, USPTO auto-expands COFFEE → COFFEES, etc.
223
360
  - International Classification (Nice Classification) codes define goods/services category
224
361
  - Serial numbers are 8 digits; Registration numbers are 7 digits
225
362
 
226
363
  ## Reference Files
227
364
 
228
365
  - `references/field-guide.md` — Full field descriptions and Nice Classification codes
229
- - `references/scraping-fallback.md` — Web scraping approach if API is unavailable
366
+ - `references/scraping-fallback.md` — Browser automation fallback details
230
367
  - `scripts/tm_search.py` — Ready-to-use Python implementation
231
- - `scripts/tm_validate.py` — Batch validation script
232
368
 
233
369
  ---
234
370
 
@@ -237,4 +373,4 @@ Rate-limit: Add 0.5–1s delay between requests to avoid throttling.
237
373
  Always include when providing availability results:
238
374
  > "This is a preliminary search only. Trademark availability is complex and depends on many
239
375
  > factors including similar marks, geographic use, and goods/services classification. Consult a
240
- > licensed trademark attorney before filing."
376
+ > licensed trademark attorney before filing."
@@ -1,135 +1,100 @@
1
- # Web Scraping Fallback for tmsearch.uspto.gov
1
+ # Browser Automation Fallback for tmsearch.uspto.gov
2
2
 
3
- Use this when the direct backend API calls return errors or unexpected responses.
3
+ The tmsearch.uspto.gov search backend uses an Elasticsearch API at
4
+ `https://tmsearch.uspto.gov/prod-stage-v1-0-0/` but it is protected by AWS WAF bot detection.
5
+ Direct HTTP requests (curl, requests, fetch) return `403` or `Missing Authentication Token`.
4
6
 
5
- ## Background
7
+ Browser automation is the only reliable way to perform keyword searches programmatically.
6
8
 
7
- The tmsearch.uspto.gov frontend is a React SPA. The backend API it uses may change endpoint paths.
8
- If the documented endpoints in SKILL.md fail, use browser DevTools (Network tab) on
9
- https://tmsearch.uspto.gov/search/search-information to intercept the actual XHR/fetch requests
10
- being made, then replicate those in code.
9
+ ## Why Direct HTTP Doesn't Work
11
10
 
12
- ## Python Requests Approach
11
+ The site's `configuration.json` reveals:
12
+ - Search backend: `https://tmsearch.uspto.gov/prod-stage-v1-0-0/`
13
+ - WAF challenge script: loaded dynamically from `awsWafChallengeUrl`
14
+ - The browser must solve the WAF challenge to get a token that's sent with API requests
13
15
 
14
- ```python
15
- import requests
16
- import time
17
-
18
- HEADERS = {
19
- "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36",
20
- "Accept": "application/json, text/plain, */*",
21
- "Accept-Language": "en-US,en;q=0.9",
22
- "Referer": "https://tmsearch.uspto.gov/search/search-information",
23
- "Origin": "https://tmsearch.uspto.gov",
24
- }
25
-
26
- def search_trademark_web(keyword: str, status: str = "A", rows: int = 25) -> dict:
27
- """
28
- Search USPTO trademark database.
29
- status: "A" = active, "D" = dead, "" = all
30
- """
31
- session = requests.Session()
32
-
33
- # First GET the main page to get any session cookies
34
- session.get("https://tmsearch.uspto.gov/search/search-information", headers=HEADERS)
35
-
36
- # Attempt POST to backend
37
- payload = {
38
- "keyword": keyword.upper(),
39
- "searchType": "1",
40
- "statusType": status,
41
- "pluralVariants": False,
42
- "start": 0,
43
- "rows": rows
44
- }
45
-
46
- response = session.post(
47
- "https://tmsearch.uspto.gov/search/keyword",
48
- json=payload,
49
- headers=HEADERS,
50
- timeout=30
51
- )
52
-
53
- if response.status_code == 200:
54
- return response.json()
55
-
56
- # If POST fails, try GET
57
- params = {
58
- "keyword": keyword.upper(),
59
- "statusType": status,
60
- "rows": rows,
61
- "start": 0
62
- }
63
- response = session.get(
64
- "https://tmsearch.uspto.gov/search/keyword",
65
- params=params,
66
- headers=HEADERS,
67
- timeout=30
68
- )
69
-
70
- return response.json()
71
- ```
72
-
73
- ## Selenium/Playwright Approach (Last Resort)
16
+ Any attempt to call the Elasticsearch endpoint directly will fail because the WAF token
17
+ is missing from the request.
74
18
 
75
- If all HTTP approaches fail, use a headless browser to drive the UI directly:
19
+ ## Playwright Approach (Recommended)
76
20
 
77
21
  ```python
78
22
  from playwright.sync_api import sync_playwright
79
23
  import json
80
24
 
81
- def search_with_playwright(keyword: str) -> list:
25
+ def search_trademark(keyword: str, max_results: int = 25) -> dict:
26
+ """Search USPTO trademarks by keyword using browser automation."""
27
+ results = {"totalFound": 0, "trademarks": []}
28
+
82
29
  with sync_playwright() as p:
83
30
  browser = p.chromium.launch(headless=True)
84
31
  page = browser.new_page()
85
- results = []
86
-
87
- # Intercept API responses
32
+
88
33
  def handle_response(response):
89
- if "search" in response.url and response.status == 200:
34
+ if "prod-stage" in response.url and response.status == 200:
90
35
  try:
91
36
  data = response.json()
92
- if "trademarks" in data:
93
- results.extend(data["trademarks"])
94
- except:
37
+ if isinstance(data, dict) and "hits" in data:
38
+ hits = data.get("hits", {})
39
+ total = hits.get("total", {})
40
+ results["totalFound"] = total.get("value", 0) if isinstance(total, dict) else total
41
+ for hit in hits.get("hits", [])[:max_results]:
42
+ results["trademarks"].append(hit.get("_source", {}))
43
+ except Exception:
95
44
  pass
96
-
45
+
97
46
  page.on("response", handle_response)
98
47
  page.goto("https://tmsearch.uspto.gov/search/search-information")
99
-
100
- # Fill in search form
101
- page.fill('input[placeholder*="search"]', keyword)
102
- page.click('button[type="submit"]')
103
48
  page.wait_for_load_state("networkidle")
104
-
49
+
50
+ search_input = page.locator('input[type="text"]').first
51
+ search_input.fill(keyword.upper())
52
+ search_input.press("Enter")
53
+
54
+ page.wait_for_load_state("networkidle")
55
+ page.wait_for_timeout(3000)
56
+
105
57
  browser.close()
106
- return results
58
+
59
+ return results
107
60
  ```
108
61
 
109
62
  ## Install Playwright
63
+
110
64
  ```bash
111
65
  pip install playwright
112
66
  playwright install chromium
113
67
  ```
114
68
 
115
- ## Alternative: Use RapidAPI Wrapper
69
+ ## TSDR Details API (No browser needed)
70
+
71
+ For looking up a single trademark by serial number, the TSDR Details API works with plain HTTP:
72
+
73
+ ```bash
74
+ curl -s "https://tmsearch.uspto.gov/tsdr-api-v1-0-0/tsdr-api?serialNumber=78787878" \
75
+ -H "Accept: application/json"
76
+ ```
77
+
78
+ This returns JSON with case status, owner info, classes, prosecution history, etc.
79
+
80
+ ## Alternative: RapidAPI Wrapper
116
81
 
117
- If USPTO direct access is problematic, the RapidAPI unofficial wrapper is reliable:
82
+ If browser automation is not practical, the RapidAPI unofficial wrapper provides reliable
83
+ keyword search with a simple REST API:
118
84
 
119
85
  ```bash
120
86
  # Endpoint: https://uspto-trademark.p.rapidapi.com
121
87
  # Requires: RapidAPI key (freemium plan available)
122
88
 
123
- curl --request GET \
124
- --url "https://uspto-trademark.p.rapidapi.com/v1/trademarkSearch/{KEYWORD}/active" \
125
- --header "x-rapidapi-host: uspto-trademark.p.rapidapi.com" \
126
- --header "x-rapidapi-key: YOUR_RAPIDAPI_KEY"
89
+ # Keyword search
90
+ curl "https://uspto-trademark.p.rapidapi.com/v1/trademarkSearch/APPLE/active" \
91
+ -H "x-rapidapi-host: uspto-trademark.p.rapidapi.com" \
92
+ -H "x-rapidapi-key: YOUR_RAPIDAPI_KEY"
127
93
 
128
94
  # Availability check
129
- curl --request GET \
130
- --url "https://uspto-trademark.p.rapidapi.com/v1/trademarkAvailable/{KEYWORD}" \
131
- --header "x-rapidapi-host: uspto-trademark.p.rapidapi.com" \
132
- --header "x-rapidapi-key: YOUR_RAPIDAPI_KEY"
95
+ curl "https://uspto-trademark.p.rapidapi.com/v1/trademarkAvailable/CLOUDPEAK" \
96
+ -H "x-rapidapi-host: uspto-trademark.p.rapidapi.com" \
97
+ -H "x-rapidapi-key: YOUR_RAPIDAPI_KEY"
133
98
  ```
134
99
 
135
100
  RapidAPI wrapper endpoints:
@@ -137,4 +102,4 @@ RapidAPI wrapper endpoints:
137
102
  - `/v1/trademarkAvailable/{keyword}` — simple yes/no availability
138
103
  - `/v1/ownerSearch/{owner_name}/{postcode}` — search by owner
139
104
  - `/v1/serialSearch/{serial_number}` — lookup by serial number
140
- - `/v1/batchTrademarkSearch` — multiple keywords (POST)
105
+ - `/v1/batchTrademarkSearch` — multiple keywords (POST)