{"id":"263dff0c-dcb6-425c-b81f-f7faaab783bc","entityType":"agent","slug":"clawhub-crawlora-org-serp-keyword-research","name":"serp-keyword-research","canonicalUrl":"https://www.xpersona.co/agent/clawhub-crawlora-org-serp-keyword-research","canonicalPath":"/agent/clawhub-crawlora-org-serp-keyword-research","generatedAt":"2026-10-11T10:51:52.339Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T08:43:13.771Z","emptyReason":null},"description":"Runs SERP and keyword research via the Crawlora API — Google, Bing, Brave, DuckDuckGo, and Yahoo search results plus Google Trends interest-over-time and related/rising queries — returning clean JSON. Use when the user wants search-engine rankings, SERP snapshots, autocomplete/keyword suggestions, or trend data instead of scraping result pages.","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.1K downloads reported by the source. Last updated 10/11/2026.","installCommand":"clawhub skill install s17d53nb8nd03gyyfdy32rgde58e574f:serp-keyword-research","sourceUrl":"https://clawhub.ai/crawlora-org/serp-keyword-research","homepage":"https://clawhub.ai/crawlora-org/skills/serp-keyword-research","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/crawlora-org/serp-keyword-research","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/crawlora-org/skills/serp-keyword-research","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":61,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"serp-keyword-research technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-11T08:43:13.771Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T08:43:13.771Z","emptyReason":null},"stars":null,"forks":null,"downloads":1109,"packageName":null,"latestVersion":"1.0.21","tractionLabel":"1.1K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T08:43:13.758Z","emptyReason":null},"lastUpdatedAt":"2026-10-11T08:43:13.771Z","lastCrawledAt":"2026-10-11T08:43:13.758Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-12T08:43:13.758Z","lastVerifiedAt":null,"highlights":[{"version":"1.0.21","createdAt":"2026-10-06T01:59:30.777Z","changelog":"Sync skill instructions, references, and helper from GitHub a91c30113b1827d719267576bbd2936c99a28029","fileCount":5,"zipByteSize":11150},{"version":"1.0.20","createdAt":"2026-09-21T01:50:55.864Z","changelog":"Sync skill instructions, references, and helper from GitHub 0cfbceba40b050ba434a0a3f4945ca97b668c805","fileCount":5,"zipByteSize":11043},{"version":"1.0.19","createdAt":"2026-09-17T10:20:39.260Z","changelog":"Security hardening: generated helpers now enforce exact routes, methods, and credential-safe curl behavior.","fileCount":5,"zipByteSize":10769},{"version":"1.0.18","createdAt":"2026-09-17T09:52:41.479Z","changelog":"Security hardening: disable inherited curl configuration for credential-bearing requests.","fileCount":5,"zipByteSize":10815},{"version":"1.0.17","createdAt":"2026-09-14T03:59:04.503Z","changelog":"Security scope hardening and documented capability alignment from GitHub d47e9935b124fd09c81c6eeda19789073b4fda20","fileCount":5,"zipByteSize":10656},{"version":"1.0.16","createdAt":"2026-09-14T02:07:44.281Z","changelog":"Sync skill instructions, references, and helper from GitHub 902f58316c643ffbcabc57fc6f15f59d27ec063d","fileCount":5,"zipByteSize":12343},{"version":"1.0.15","createdAt":"2026-09-10T12:35:40.344Z","changelog":"Validate API keys before curl config","fileCount":5,"zipByteSize":11965},{"version":"1.0.14","createdAt":"2026-09-10T12:16:48.870Z","changelog":"Keep API keys out of process arguments","fileCount":5,"zipByteSize":11918}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s17d53nb8nd03gyyfdy32rgde58e574f:serp-keyword-research","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s17d53nb8nd03gyyfdy32rgde58e574f:serp-keyword-research` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/crawlora-org/serp-keyword-research before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-crawlora-org-serp-keyword-research/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-crawlora-org-serp-keyword-research/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-crawlora-org-serp-keyword-research/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-crawlora-org-serp-keyword-research/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-crawlora-org-serp-keyword-research/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-crawlora-org-serp-keyword-research/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-11T10:51:52.336Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-crawlora-org-serp-keyword-research/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-crawlora-org-serp-keyword-research/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-crawlora-org-serp-keyword-research/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-crawlora-org-serp-keyword-research/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T08:43:13.771Z","emptyReason":null},"readme":"Skill: serp-keyword-research\n\nOwner: crawlora-org\n\nSummary: Runs SERP and keyword research via the Crawlora API — Google, Bing, Brave, DuckDuckGo, and Yahoo search results plus Google Trends interest-over-time and related/rising queries — returning clean JSON. Use when the user wants search-engine rankings, SERP snapshots, autocomplete/keyword suggestions, or trend data instead of scraping result pages.\n\nTags: latest:1.0.21\n\nVersion history:\n\nv1.0.21 | 2026-10-06T01:59:30.777Z | user\n\nSync skill instructions, references, and helper from GitHub a91c30113b1827d719267576bbd2936c99a28029\n\nv1.0.20 | 2026-09-21T01:50:55.864Z | user\n\nSync skill instructions, references, and helper from GitHub 0cfbceba40b050ba434a0a3f4945ca97b668c805\n\nv1.0.19 | 2026-09-17T10:20:39.260Z | user\n\nSecurity hardening: generated helpers now enforce exact routes, methods, and credential-safe curl behavior.\n\nv1.0.18 | 2026-09-17T09:52:41.479Z | user\n\nSecurity hardening: disable inherited curl configuration for credential-bearing requests.\n\nv1.0.17 | 2026-09-14T03:59:04.503Z | user\n\nSecurity scope hardening and documented capability alignment from GitHub d47e9935b124fd09c81c6eeda19789073b4fda20\n\nv1.0.16 | 2026-09-14T02:07:44.281Z | user\n\nSync skill instructions, references, and helper from GitHub 902f58316c643ffbcabc57fc6f15f59d27ec063d\n\nv1.0.15 | 2026-09-10T12:35:40.344Z | user\n\nValidate API keys before curl config\n\nv1.0.14 | 2026-09-10T12:16:48.870Z | user\n\nKeep API keys out of process arguments\n\nv1.0.13 | 2026-09-10T12:07:47.115Z | user\n\nReject curl local-file query syntax\n\nv1.0.12 | 2026-09-10T11:55:19.995Z | user\n\nStream helper request bodies through curl stdin\n\nv1.0.11 | 2026-09-10T11:43:31.792Z | user\n\nScope helper routes and remove secret-shaped key examples\n\nv1.0.10 | 2026-09-10T07:05:24.988Z | user\n\nMigrate publisher from tonywangcn to crawlora-org for brand consistency with the plugins\n\nv1.0.9 | 2026-09-08T04:35:56.002Z | user\n\nRefresh stale REST examples, endpoint references, and Bash helper from crawlora-skills 1.17.1.\n\nv1.0.8 | 2026-09-07T13:32:39.377Z | user\n\nSync via scripts/sync-directories.sh\n\nv1.0.7 | 2026-09-07T08:16:19.297Z | user\n\nSync via scripts/sync-directories.sh\n\nv1.0.6 | 2026-09-07T06:40:10.278Z | user\n\nSync via scripts/sync-directories.sh\n\nv1.0.5 | 2026-08-24T07:18:17.365Z | user\n\nSync via scripts/sync-directories.sh\n\nv1.0.4 | 2026-08-24T06:30:03.600Z | user\n\nSync via scripts/sync-directories.sh\n\nv1.0.3 | 2026-08-24T05:12:08.732Z | user\n\nSync via scripts/sync-directories.sh\n\nv1.0.2 | 2026-08-14T18:29:30.753Z | user\n\nSync via scripts/sync-directories.sh\n\nv1.0.1 | 2026-08-10T18:32:00.877Z | user\n\nSet categories\n\nv1.0.0 | 2026-08-10T18:04:47.889Z | auto\n\nInitial release of serp-keyword-research:\n\n- Enables fast SERP analysis and keyword/trend research across Google, Bing, Brave, DuckDuckGo, Yahoo, and Google Trends using the Crawlora API.\n- Returns clean, normalized JSON with search rankings, autocomplete/keyword suggestions, trend data, and related/rising queries.\n- Guides setup and secure use of the free Crawlora API key (2,000 credits/month).\n- Includes complete endpoint list, usage examples, and practical instructions for API calls and result parsing.\n- Supports SEO monitoring, keyword discovery, and search trend analysis without scraping result pages directly.\n\nArchive index:\n\nArchive v1.0.21: 5 files, 11150 bytes\n\nFiles: reference/endpoints.md (25114b), scripts/crawlora.sh (7822b), skill-card.md (1720b), SKILL.md (4420b), _meta.json (141b)\n\nFile v1.0.21:SKILL.md\n\n---\nname: serp-keyword-research\ndescription: Runs SERP and keyword research via the Crawlora API — Google, Bing, Brave, DuckDuckGo, and Yahoo search results plus Google Trends interest-over-time and related/rising queries — returning clean JSON. Use when the user wants search-engine rankings, SERP snapshots, autocomplete/keyword suggestions, or trend data instead of scraping result pages.\n---\n\n# SERP & keyword research\n\nCapture search-engine results (Google, Bing, Brave, DuckDuckGo, Yahoo) and\nkeyword/trend signals (Google autosuggest, Google Trends) as normalized\nJSON from the Crawlora API.\n\n## When to use this skill\n\n- \"What ranks for <query> on Google / Bing?\" / \"snapshot the SERP for …\".\n- \"Keyword ideas / autocomplete for …\" (suggest endpoints).\n- \"Is <topic> trending?\" / \"interest over time / by region for <keyword>.\"\n- \"Related and rising queries for …\" (Google Trends).\n- SEO/SERP monitoring, keyword discovery, or trend research.\n\n## Setup (one-time)\n\n- Get a free Crawlora API key (2,000 credits/mo, no card) at [https://crawlora.net](https://crawlora.net?utm_source=github&utm_medium=referral&utm_campaign=crawlora-skills).\n- Set `CRAWLORA_API_KEY` in the environment before running the helper.\n- The helper reads `CRAWLORA_API_KEY` from the environment and sends requests to `https://api.crawlora.net/api/v1`. Missing/invalid key → `401`.\n\n## How it works\n\n1. **SERP** — Google search is `POST /google/search` with flat `keyword`, `language`, and `country` fields;\n   Bing, Brave, DuckDuckGo, and Yahoo are plain `GET` with `q`:\n   `/bing/search`, `/brave/search`, `/duckduckgo/search`, `/yahoo-search/search`.\n   Cross-check engines for coverage; on a `503` challenge, fall back to another engine.\n2. **Verticals** — news/videos/images per engine (`/google/news`, `/bing/videos`,\n   `/duckduckgo/news`, `/duckduckgo/image`, `/duckduckgo/video`, `/duckduckgo/shopping`, …).\n3. **Keyword ideas** — autosuggest: `GET /google/suggest?q=...` (and `/bing/suggest`,\n   `/brave/suggest`).\n4. **Trends** — Google Trends `POST` endpoints:\n   `/google/trends/explore/interest-over-time`, `/interest-by-region`,\n   `/related-topics`, `/rising-queries`, `/top-queries` (body: `{\"keywords\":[...]}`),\n   plus `GET /google/trends/trending` for what's hot now.\n\nFull endpoint list, methods, and params: [`reference/endpoints.md`](reference/endpoints.md).\n\n## Calling the API\n\n```sh\n# GET search engines + suggest:\nscripts/crawlora.sh /bing/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /brave/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /duckduckgo/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /yahoo-search/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /google/suggest q=\"web scraping\" | jq '.'\n\n# POST endpoints take a JSON body (note -X POST):\nscripts/crawlora.sh -X POST /google/search '{\"keyword\":\"web scraping api\",\"language\":\"en\",\"country\":\"us\"}' | jq '.'\nscripts/crawlora.sh -X POST /google/trends/explore/interest-over-time '{\"keywords\":[\"web scraping\"]}' | jq '.'\n```\n\nUse `scripts/crawlora.sh` for all requests; it keeps the API key out of command-line arguments.\n\n\n## Endpoint reference\n\nSee [`reference/endpoints.md`](reference/endpoints.md) for every Google, Bing,\nBrave, DuckDuckGo, Yahoo, and Google Trends endpoint this skill uses (method,\npath, params, description).\n\n## Examples\n\n- **SERP snapshot:** `POST /google/search` (and `/bing/search`) for a target query;\n  record the ranked result titles/URLs to track positions over time.\n- **Keyword expansion:** seed term → `/google/suggest` → for each suggestion,\n  `POST /google/trends/explore/rising-queries` to find momentum.\n- **Trend check:** `POST /google/trends/explore/interest-over-time` with\n  `{\"keywords\":[\"electric bikes\",\"e-bikes\"]}` and compare the series.\n\n## Notes & limits\n\n- **Credits / pay-on-success:** billed only on `2xx`; free tier 2,000 credits/mo.\n  Key at [https://crawlora.net](https://crawlora.net?utm_source=github&utm_medium=referral&utm_campaign=crawlora-skills).\n- **Public data only** — public search results; respect each engine's terms.\n- **Security:** key lives in `CRAWLORA_API_KEY` only — never hardcode, query-param, or commit it.\n- Search endpoints may return `503` when the engine serves a challenge page —\n  retry or switch engines (Google ↔ Bing ↔ Brave). Google search is rate-limited\n  to ~1 req/s (`429` on excess).\n\nFile v1.0.21:_meta.json\n\n{\n  \"ownerId\": \"kn70shhkf6qpfwgfrbgtep2wkd8c6b4t\",\n  \"slug\": \"serp-keyword-research\",\n  \"version\": \"1.0.21\",\n  \"publishedAt\": 1791251970777\n}\n\nFile v1.0.21:reference/endpoints.md\n\n# serp-keyword-research — endpoint reference\n\n> Generated from `scripts/tools.json` by `scripts/generate.mjs` — do not edit by hand.\n\nEndpoints this skill uses, grouped by platform. Call them via `scripts/crawlora.sh` (see SKILL.md).\n\nAll paths are relative to the API base `https://api.crawlora.net/api/v1` and require the header `x-api-key: $CRAWLORA_API_KEY`. Path params like `{id}` are substituted into the URL; `GET` params go in the query string; `POST` params go in a JSON body.\n\n**37 endpoints across 5 platform group(s).**\n\n## Google (15)\n\n### `google_news`\n\n- **HTTP:** `GET /google/news`\n- **What:** Search Google News. Returns current Google News search results using anonymous HTTP requests with fresh proxy profiles, without browser rendering. Pages slice the finite result snapshot; they do not traverse the Google Search index. Results include title, source, publisher article URL, age, and thumbnail when available. Valid no-results searches and exhausted pages return an empty array. Locale defaults to country=us and lang=en. Returns 503 for blocked or malformed upstream responses.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Google UI language; defaults to en; `page` (integer, optional) — 1-based page within the current finite result snapshot; defaults to 1; `q` (string, **required**) — Search query\n\n### `google_news_search`\n\n- **HTTP:** `POST /google/news`\n- **What:** Search Google News with JSON. Restored JSON compatibility endpoint. Returns current Google News articles using anonymous HTTP requests with fresh proxy profiles, without browser rendering. Pages slice the finite current result snapshot. Uses the legacy result array and field names; no-results searches and exhausted pages return an empty result array.\n- **Params:** `searchOption` (object, **required**) — Search options; keyword, language and country are required. limit defaults to 10 and is clamped to 10..100; page defaults to 1.\n- **REST body:** Send the value of the MCP argument `searchOption` directly as the JSON body; do not wrap it in a `searchOption` property.\n\n### `google_suggest`\n\n- **HTTP:** `GET /google/suggest`\n- **What:** Suggest Google search queries. Returns Google autosuggest query completions from the public unauthenticated suggest JSON endpoint. `source` selects the web, YouTube, or shopping suggestion list, and `rich=true` adds a type, relevance score, and short description to each suggestion.\n- **Params:** `count` (integer, optional) — Suggestions to return; defaults to 10, clamped to 1..12; `country` (string, optional) — Google result country; defaults to us; `lang` (string, optional) — Google UI language; defaults to en; `q` (string, **required**) — Search query prefix; `rich` (boolean, optional) — Add Google's type, relevance score, and description to each suggestion; defaults to false; `source` (string, optional) — Suggestion source; defaults to web\n\n### `google_trends_categories`\n\n- **HTTP:** `GET /google/trends/categories`\n- **What:** Google Trends categories. Returns supported top-level Google Trends category ids and labels for Trending Now category filters.\n- **Params:** _none_\n\n### `google_trends_enums`\n\n- **HTTP:** `GET /google/trends/enums`\n- **What:** Google Trends enum metadata. Returns supported Google Trends enum values for explore/trending filters, including locations, date ranges, search types, categories, statuses, and sort modes.\n- **Params:** _none_\n\n### `google_trends_explore`\n\n- **HTTP:** `POST /google/trends/explore`\n- **What:** Google Trends explore data. Returns normalized Google Trends keyword analytics from internal Trends widget requests: interest over time, interest by region, related queries, and related topics when available.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_explore_interest_by_region`\n\n- **HTTP:** `POST /google/trends/explore/interest-by-region`\n- **What:** Google Trends interest by region. Returns only the interest-by-region widget from the Google Trends Explore widget flow. Supports multiple comparison terms and returns an empty interest_by_region array when Google returns no rows.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_explore_interest_over_time`\n\n- **HTTP:** `POST /google/trends/explore/interest-over-time`\n- **What:** Google Trends interest over time. Returns only the interest-over-time timeline from the Google Trends Explore widget flow. Supports multiple comparison terms.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_explore_related_topics`\n\n- **HTTP:** `POST /google/trends/explore/related-topics`\n- **What:** Google Trends related topics. Returns only the related topics widget from the Google Trends Explore widget flow. Returns an empty related_topics array when Google returns no topic rows for the requested term/filter combination.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_explore_rising_queries`\n\n- **HTTP:** `POST /google/trends/explore/rising-queries`\n- **What:** Google Trends explore rising queries. Returns the Rising related queries widget for one or more Google Trends explore terms. Returns an empty queries array when Google returns no rows for the requested term/filter combination.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_explore_top_queries`\n\n- **HTTP:** `POST /google/trends/explore/top-queries`\n- **What:** Google Trends explore top queries. Returns the Top related queries widget for one or more Google Trends explore terms. Returns an empty queries array when Google returns no rows for the requested term/filter combination.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_locations`\n\n- **HTTP:** `GET /google/trends/locations`\n- **What:** Google Trends locations. Returns supported Google Trends location codes. Explore endpoints also accept WORLDWIDE.\n- **Params:** _none_\n\n### `google_trends_trending`\n\n- **HTTP:** `GET /google/trends/trending`\n- **What:** Google Trends trending now data. Returns normalized Google Trends Trending Now rows from the internal TrendsUi batch RPC replay.\n- **Params:** `category` (integer, optional) — Trending category id; `geo` (string, optional) — Country/territory location code; `hl` (string, optional) — Google Trends UI locale; `limit` (integer, optional) — Maximum rows to return; `sort_by` (string, optional) — Sort mode; `status` (string, optional) — Trend status filter; `time_range` (string, optional) — Alias for window; `tz` (integer, optional) — Timezone offset minutes; `window` (string, optional) — Trend window\n\n### `google_trends_trending_detail`\n\n- **HTTP:** `POST /google/trends/trending/detail`\n- **What:** Google Trends trending term detail. Returns the Explore detail widgets for a single trending term, including interest over time, regional interest, top/rising related queries, and related topics when Google returns them.\n- **Params:** `request` (object, **required**) — Trending detail request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_videos`\n\n- **HTTP:** `GET /google/videos`\n- **What:** Search Google video results. Returns normalized Google video vertical results (title, platform, link, duration, age) parsed from the public Google video results page. Locale defaults to country=us and lang=en. Returns 503 when Google serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Google UI language; defaults to en; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n## Bing (5)\n\n### `bing_images`\n\n- **HTTP:** `GET /bing/images`\n- **What:** Search Bing image results. Returns normalized Bing image search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Bing image HTML/async pages and return 503 when Bing serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Bing UI language; defaults to en-us; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n### `bing_news`\n\n- **HTTP:** `GET /bing/news`\n- **What:** Search Bing news results. Returns normalized Bing news search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Bing news HTML/async pages and return 503 when Bing serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Bing UI language; defaults to en-us; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n### `bing_search`\n\n- **HTTP:** `GET /bing/search`\n- **What:** Search Bing web results. Returns normalized Bing web search results for a query string, including organic results, optional context panel data, related queries, people-also-ask questions, news modules, video modules, and page-based pagination. Empty optional blocks are omitted from the JSON response. Locale defaults to country=us and lang=en-us. Results are fetched with a Chrome-impersonated request client and return 503 on a genuine transport failure or challenge page. Bing occasionally serves a well-formed page whose results share no significant term with the query; when every hedged attempt hits this, the response is still returned as 200 with data.low_confidence set to true (and the X-Low-Confidence header) instead of being withheld, so callers get Bing's real answer plus an honest signal to double-check it rather than nothing. Queries that use the site: operator (for example site:gov.hu) are not supported: Bing serves a bot-verification challenge for them, so they are rejected with 400 before any request is made. Use the DuckDuckGo (/api/v1/duckduckgo/search), Brave (/api/v1/brave/search), or Yahoo (/api/v1/yahoo-search/search) search endpoints for domain-restricted searches instead.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Bing UI language; defaults to en-us; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n### `bing_suggest`\n\n- **HTTP:** `GET /bing/suggest`\n- **What:** Suggest Bing search queries. Returns Bing autosuggest query completions for a query prefix. Locale defaults to country=us and lang=en-us. Suggestions are fetched from public Bing suggest endpoints and trimmed to the requested count. `rich=true` adds entity cards (name, description, image) where Bing shows them.\n- **Params:** `count` (integer, optional) — Suggestions to return; defaults to 10, clamped to 1..12; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Bing UI language; defaults to en-us; `q` (string, **required**) — Search query prefix; `rich` (boolean, optional) — Add entity name, description, and image to suggestions Bing resolves to a known entity; defaults to false\n\n### `bing_videos`\n\n- **HTTP:** `GET /bing/videos`\n- **What:** Search Bing video results. Returns normalized Bing video search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Bing video HTML/async pages and return 503 when Bing serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Bing UI language; defaults to en-us; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n## Brave (5)\n\n### `brave_images`\n\n- **HTTP:** `GET /brave/images`\n- **What:** Search Brave image results. Returns normalized Brave image search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Brave Search image HTML and return 503 when Brave serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results to return; defaults to 10, clamped to 1..50; `country` (string, optional) — Brave result country; defaults to us; `lang` (string, optional) — Brave UI language; defaults to en-us; `offset` (integer, optional) — Zero-based Brave result page; defaults to 0; `q` (string, **required**) — Search query\n\n### `brave_news`\n\n- **HTTP:** `GET /brave/news`\n- **What:** Search Brave news results. Returns normalized Brave news search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Brave Search news HTML and return 503 when Brave serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results to return; defaults to 10, clamped to 1..50; `country` (string, optional) — Brave result country; defaults to us; `date_from` (string, optional) — Custom start date in YYYY-MM-DD; requires date_to; `date_to` (string, optional) — Custom end date in YYYY-MM-DD; requires date_from; `lang` (string, optional) — Brave UI language; defaults to en-us; `offset` (integer, optional) — Zero-based Brave result page; defaults to 0; `q` (string, **required**) — Search query; `time_range` (string, optional) — Preset time filter: any, day, week, month, year, or custom\n\n### `brave_search`\n\n- **HTTP:** `GET /brave/search`\n- **What:** Search Brave. Returns normalized web search results from Brave Search for a query string, along with offset-based pagination, related queries, discussions, videos, and the right-side knowledge card when Brave includes one. Use time_range for preset ranges or date_from/date_to for a custom YYYY-MM-DD range. Locale defaults to country=us and lang=en-us.\n- **Params:** `country` (string, optional) — Brave result country; defaults to us; `date_from` (string, optional) — Custom start date in YYYY-MM-DD; requires date_to; `date_to` (string, optional) — Custom end date in YYYY-MM-DD; requires date_from; `lang` (string, optional) — Brave UI language; defaults to en-us; `offset` (integer, optional) — Zero-based Brave result page; `q` (string, **required**) — Search query; `time_range` (string, optional) — Preset time filter: any, day, week, month, year, or custom\n\n### `brave_suggest`\n\n- **HTTP:** `GET /brave/suggest`\n- **What:** Suggest Brave search queries. Returns Brave autosuggest query completions for a query prefix. Locale defaults to country=us and lang=en-us. Suggestions are fetched from public Brave Search suggest JSON and trimmed to the requested count. `rich=true` adds entity metadata (name, description, category, image) where Brave resolves a suggestion to a known entity.\n- **Params:** `count` (integer, optional) — Suggestions to return; defaults to 10, clamped to 1..12; `country` (string, optional) — Brave result country; defaults to us; `lang` (string, optional) — Brave UI language; defaults to en-us; `q` (string, **required**) — Search query prefix; `rich` (boolean, optional) — Add entity name, description, category, and image to suggestions Brave resolves to a known entity; defaults to false\n\n### `brave_videos`\n\n- **HTTP:** `GET /brave/videos`\n- **What:** Search Brave video results. Returns normalized Brave video search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Brave Search video HTML and return 503 when Brave serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results to return; defaults to 10, clamped to 1..50; `country` (string, optional) — Brave result country; defaults to us; `date_from` (string, optional) — Custom start date in YYYY-MM-DD; requires date_to; `date_to` (string, optional) — Custom end date in YYYY-MM-DD; requires date_from; `lang` (string, optional) — Brave UI language; defaults to en-us; `offset` (integer, optional) — Zero-based Brave result page; defaults to 0; `q` (string, **required**) — Search query; `time_range` (string, optional) — Preset time filter: any, day, week, month, year, or custom\n\n## DuckDuckGo Search (6)\n\n### `duckduckgo_image`\n\n- **HTTP:** `GET /duckduckgo/image`\n- **What:** Search DuckDuckGo image results. Returns normalized DuckDuckGo image results for a query string: title, source page URL, image URL, thumbnail, dimensions, and hostname, plus page-based pagination. Results are fetched from DuckDuckGo's own image JSON API.\n- **Params:** `page` (integer, optional) — 1-based page number, defaults to 1; `q` (string, **required**) — Search query; `region` (string, optional) — DuckDuckGo region/locale code, e.g. us-en, uk-en, wt-wt (worldwide, the default)\n\n### `duckduckgo_news`\n\n- **HTTP:** `GET /duckduckgo/news`\n- **What:** Search DuckDuckGo news results. Returns normalized DuckDuckGo news results for a query string: title, destination URL, source, excerpt, thumbnail, and relative/published time, plus page-based pagination. Results are fetched from DuckDuckGo's own news JSON API.\n- **Params:** `page` (integer, optional) — 1-based page number, defaults to 1; `q` (string, **required**) — Search query; `region` (string, optional) — DuckDuckGo region/locale code, e.g. us-en, uk-en, wt-wt (worldwide, the default)\n\n### `duckduckgo_search`\n\n- **HTTP:** `GET /duckduckgo/search`\n- **What:** Search DuckDuckGo web results. Returns normalized DuckDuckGo web search results for a query string: title, destination URL, description, and hostname, plus page-based pagination. DuckDuckGo wraps every result link in its own click-tracking redirect; this endpoint always returns the decoded destination URL, never the raw redirect link. Results are fetched from DuckDuckGo's own server-rendered search page.\n- **Params:** `page` (integer, optional) — 1-based page number, defaults to 1; `q` (string, **required**) — Search query; `region` (string, optional) — DuckDuckGo region/locale code, e.g. us-en, uk-en, wt-wt (worldwide, the default); `safe_search` (string, optional) — Safe search level, defaults to DuckDuckGo's own moderate setting when omitted; `time_range` (string, optional) — Restrict results to a recency window\n\n### `duckduckgo_shopping`\n\n- **HTTP:** `GET /duckduckgo/shopping`\n- **What:** Search DuckDuckGo shopping results. Returns normalized DuckDuckGo shopping results for a query string: title, brand, merchant, description, price, rating, and review count, plus total page count. DuckDuckGo's shopping vertical is ad-funded, syndicated product listings, not organic content; every product link is wrapped in an ad-click-tracking redirect with no clean destination to unwrap, so no destination URL is returned. DuckDuckGo's own pagination token for this vertical is an opaque per-response blob rather than a plain page offset, so only the first page is supported.\n- **Params:** `q` (string, **required**) — Search query; `region` (string, optional) — DuckDuckGo market code, e.g. us-en, uk-en\n\n### `duckduckgo_suggest`\n\n- **HTTP:** `GET /duckduckgo/suggest`\n- **What:** Suggest DuckDuckGo search queries. Returns DuckDuckGo search-box autocomplete completions for a query prefix, in DuckDuckGo's own ranking order. DuckDuckGo never returns more than 8 suggestions per prefix.\n- **Params:** `count` (integer, optional) — Suggestions to return; defaults to 8, clamped to 1..8; `q` (string, **required**) — Search query prefix; `region` (string, optional) — DuckDuckGo region code such as us-en, uk-en, de-de, or wt-wt (worldwide, the default)\n\n### `duckduckgo_video`\n\n- **HTTP:** `GET /duckduckgo/video`\n- **What:** Search DuckDuckGo video results. Returns normalized DuckDuckGo video results for a query string: title, destination URL, description, duration, thumbnail, publisher/uploader, published time, and view count, plus page-based pagination. Results are fetched from DuckDuckGo's own video JSON API.\n- **Params:** `page` (integer, optional) — 1-based page number, defaults to 1; `q` (string, **required**) — Search query; `region` (string, optional) — DuckDuckGo region/locale code, e.g. us-en, uk-en, wt-wt (worldwide, the default)\n\n## Yahoo Search (6)\n\n### `yahoo_search`\n\n- **HTTP:** `GET /yahoo-search/search`\n- **What:** Search Yahoo web results. Returns normalized Yahoo web search results for a query string: title, destination URL, description, and hostname, plus page-based pagination. Yahoo wraps every result link in its own click-tracking redirect; this endpoint always returns the decoded destination URL, never the raw redirect link. Results are fetched from Yahoo's own server-rendered search page.\n- **Params:** `page` (integer, optional) — 1-based page number, defaults to 1; `q` (string, **required**) — Search query; `time_range` (string, optional) — Restrict results by recency. Omit for unfiltered ('Anytime').\n\n### `yahoo_search_images`\n\n- **HTTP:** `GET /yahoo-search/images`\n- **What:** Search Yahoo image results. Returns Yahoo's image-search results for a query: title, direct image URL, the page hosting the image, source domain, thumbnail, and original image dimensions when available. Results are fetched from Yahoo's own server-rendered image-search page.\n- **Params:** `q` (string, **required**) — Search query\n\n### `yahoo_search_local`\n\n- **HTTP:** `GET /yahoo-search/local`\n- **What:** Search Yahoo local business results. Returns Yahoo's local-business-search results for a query: name, category, price range, address, phone, open status, rating, and review count. Location is resolved from the query text itself, the same way a user would type into Yahoo's own local search box (e.g. \"pizza near seattle wa\"), not a separate coordinate parameter. Results are fetched from Yahoo's own server-rendered local-search page.\n- **Params:** `q` (string, **required**) — Search query, including any location intent\n\n### `yahoo_search_news`\n\n- **HTTP:** `GET /yahoo-search/news`\n- **What:** Search Yahoo news results. Returns Yahoo's news-search results for a query: title, destination URL, description, source, and relative publish age. Results are fetched from Yahoo's own server-rendered news-search page (news.search.yahoo.com) -- a distinct product from the yahoo-news family, which covers the www.yahoo.com/news portal itself. Yahoo wraps every result link in its own click-tracking redirect; this endpoint always returns the decoded destination URL, never the raw redirect link.\n- **Params:** `q` (string, **required**) — Search query\n\n### `yahoo_search_suggest`\n\n- **HTTP:** `GET /yahoo-search/suggest`\n- **What:** Yahoo web search autocomplete suggestions. Returns Yahoo's own search-box autocomplete suggestions for a partial query: a flat list of suggested search terms, each optionally carrying knowledge-panel entity metadata (type, image, subtitle, description) when Yahoo resolves the term to a known company, place, product, or similar entity rather than a plain phrase.\n- **Params:** `count` (integer, optional) — Number of suggestions to return, default 10, clamped to 1..20; `q` (string, **required**) — Partial search query to autocomplete\n\n### `yahoo_search_videos`\n\n- **HTTP:** `GET /yahoo-search/videos`\n- **What:** Search Yahoo video results. Returns Yahoo's video-search results for a query: title, destination page URL, source domain, description, thumbnail, and duration. Results are fetched from Yahoo's own server-rendered video-search page.\n- **Params:** `q` (string, **required**) — Search query\n\nFile v1.0.21:skill-card.md\n\n## Description:\n\nRuns search-engine results, keyword suggestions, and Google Trends research through the Crawlora API, returning structured JSON.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[crawlora-org](https://clawhub.ai/user/crawlora-org)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nSEO practitioners, marketers, and developers use this skill to compare public search rankings, discover related keywords, and examine search trends across engines and regions.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Search terms and trend keywords are sent to Crawlora and related search providers.\n\nMitigation: Use only public, non-sensitive queries; do not submit secrets, private identifiers, or regulated data.\n\nRisk: An exposed Crawlora API key could allow unauthorized use.\n\nMitigation: Keep CRAWLORA_API_KEY in the environment; never hardcode or commit it.\n\n## Reference(s):\n\n- [Endpoint reference](reference/endpoints.md)\n- [ClawHub skill release](https://clawhub.ai/crawlora-org/skills/serp-keyword-research)\n\n## Skill Output:\n\n**Output Type(s):** [Text, JSON, Guidance]\n\n**Output Format:** [Plain text or Markdown summaries with structured JSON results]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Results reflect public search and trends data; coverage and availability vary by engine.]\n\n## Skill Version(s):\n\n1.0.21 (source: ClawHub release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.0.20: 5 files, 11043 bytes\n\nFiles: reference/endpoints.md (23728b), scripts/crawlora.sh (7747b), skill-card.md (2348b), SKILL.md (4420b), _meta.json (141b)\n\nFile v1.0.20:SKILL.md\n\n---\nname: serp-keyword-research\ndescription: Runs SERP and keyword research via the Crawlora API — Google, Bing, Brave, DuckDuckGo, and Yahoo search results plus Google Trends interest-over-time and related/rising queries — returning clean JSON. Use when the user wants search-engine rankings, SERP snapshots, autocomplete/keyword suggestions, or trend data instead of scraping result pages.\n---\n\n# SERP & keyword research\n\nCapture search-engine results (Google, Bing, Brave, DuckDuckGo, Yahoo) and\nkeyword/trend signals (Google autosuggest, Google Trends) as normalized\nJSON from the Crawlora API.\n\n## When to use this skill\n\n- \"What ranks for <query> on Google / Bing?\" / \"snapshot the SERP for …\".\n- \"Keyword ideas / autocomplete for …\" (suggest endpoints).\n- \"Is <topic> trending?\" / \"interest over time / by region for <keyword>.\"\n- \"Related and rising queries for …\" (Google Trends).\n- SEO/SERP monitoring, keyword discovery, or trend research.\n\n## Setup (one-time)\n\n- Get a free Crawlora API key (2,000 credits/mo, no card) at [https://crawlora.net](https://crawlora.net?utm_source=github&utm_medium=referral&utm_campaign=crawlora-skills).\n- Set `CRAWLORA_API_KEY` in the environment before running the helper.\n- The helper reads `CRAWLORA_API_KEY` from the environment and sends requests to `https://api.crawlora.net/api/v1`. Missing/invalid key → `401`.\n\n## How it works\n\n1. **SERP** — Google search is `POST /google/search` with flat `keyword`, `language`, and `country` fields;\n   Bing, Brave, DuckDuckGo, and Yahoo are plain `GET` with `q`:\n   `/bing/search`, `/brave/search`, `/duckduckgo/search`, `/yahoo-search/search`.\n   Cross-check engines for coverage; on a `503` challenge, fall back to another engine.\n2. **Verticals** — news/videos/images per engine (`/google/news`, `/bing/videos`,\n   `/duckduckgo/news`, `/duckduckgo/image`, `/duckduckgo/video`, `/duckduckgo/shopping`, …).\n3. **Keyword ideas** — autosuggest: `GET /google/suggest?q=...` (and `/bing/suggest`,\n   `/brave/suggest`).\n4. **Trends** — Google Trends `POST` endpoints:\n   `/google/trends/explore/interest-over-time`, `/interest-by-region`,\n   `/related-topics`, `/rising-queries`, `/top-queries` (body: `{\"keywords\":[...]}`),\n   plus `GET /google/trends/trending` for what's hot now.\n\nFull endpoint list, methods, and params: [`reference/endpoints.md`](reference/endpoints.md).\n\n## Calling the API\n\n```sh\n# GET search engines + suggest:\nscripts/crawlora.sh /bing/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /brave/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /duckduckgo/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /yahoo-search/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /google/suggest q=\"web scraping\" | jq '.'\n\n# POST endpoints take a JSON body (note -X POST):\nscripts/crawlora.sh -X POST /google/search '{\"keyword\":\"web scraping api\",\"language\":\"en\",\"country\":\"us\"}' | jq '.'\nscripts/crawlora.sh -X POST /google/trends/explore/interest-over-time '{\"keywords\":[\"web scraping\"]}' | jq '.'\n```\n\nUse `scripts/crawlora.sh` for all requests; it keeps the API key out of command-line arguments.\n\n\n## Endpoint reference\n\nSee [`reference/endpoints.md`](reference/endpoints.md) for every Google, Bing,\nBrave, DuckDuckGo, Yahoo, and Google Trends endpoint this skill uses (method,\npath, params, description).\n\n## Examples\n\n- **SERP snapshot:** `POST /google/search` (and `/bing/search`) for a target query;\n  record the ranked result titles/URLs to track positions over time.\n- **Keyword expansion:** seed term → `/google/suggest` → for each suggestion,\n  `POST /google/trends/explore/rising-queries` to find momentum.\n- **Trend check:** `POST /google/trends/explore/interest-over-time` with\n  `{\"keywords\":[\"electric bikes\",\"e-bikes\"]}` and compare the series.\n\n## Notes & limits\n\n- **Credits / pay-on-success:** billed only on `2xx`; free tier 2,000 credits/mo.\n  Key at [https://crawlora.net](https://crawlora.net?utm_source=github&utm_medium=referral&utm_campaign=crawlora-skills).\n- **Public data only** — public search results; respect each engine's terms.\n- **Security:** key lives in `CRAWLORA_API_KEY` only — never hardcode, query-param, or commit it.\n- Search endpoints may return `503` when the engine serves a challenge page —\n  retry or switch engines (Google ↔ Bing ↔ Brave). Google search is rate-limited\n  to ~1 req/s (`429` on excess).\n\nFile v1.0.20:_meta.json\n\n{\n  \"ownerId\": \"kn70shhkf6qpfwgfrbgtep2wkd8c6b4t\",\n  \"slug\": \"serp-keyword-research\",\n  \"version\": \"1.0.20\",\n  \"publishedAt\": 1789955455864\n}\n\nFile v1.0.20:reference/endpoints.md\n\n# serp-keyword-research — endpoint reference\n\n> Generated from `scripts/tools.json` by `scripts/generate.mjs` — do not edit by hand.\n\nEndpoints this skill uses, grouped by platform. Call them via `scripts/crawlora.sh` (see SKILL.md).\n\nAll paths are relative to the API base `https://api.crawlora.net/api/v1` and require the header `x-api-key: $CRAWLORA_API_KEY`. Path params like `{id}` are substituted into the URL; `GET` params go in the query string; `POST` params go in a JSON body.\n\n**36 endpoints across 5 platform group(s).**\n\n## Google (15)\n\n### `google_news`\n\n- **HTTP:** `GET /google/news`\n- **What:** Search Google News. Returns current Google News search results using anonymous HTTP requests with fresh proxy profiles, without browser rendering. Pages slice the finite result snapshot; they do not traverse the Google Search index. Results include title, source, publisher article URL, age, and thumbnail when available. Valid no-results searches and exhausted pages return an empty array. Locale defaults to country=us and lang=en. Returns 503 for blocked or malformed upstream responses.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Google UI language; defaults to en; `page` (integer, optional) — 1-based page within the current finite result snapshot; defaults to 1; `q` (string, **required**) — Search query\n\n### `google_news_search`\n\n- **HTTP:** `POST /google/news`\n- **What:** Search Google News with JSON. Restored JSON compatibility endpoint. Returns current Google News articles using anonymous HTTP requests with fresh proxy profiles, without browser rendering. Pages slice the finite current result snapshot. Uses the legacy result array and field names; no-results searches and exhausted pages return an empty result array.\n- **Params:** `searchOption` (object, **required**) — Search options; keyword, language and country are required. limit defaults to 10 and is clamped to 10..100; page defaults to 1.\n- **REST body:** Send the value of the MCP argument `searchOption` directly as the JSON body; do not wrap it in a `searchOption` property.\n\n### `google_suggest`\n\n- **HTTP:** `GET /google/suggest`\n- **What:** Suggest Google search queries. Returns Google autosuggest query completions from the public unauthenticated suggest JSON endpoint.\n- **Params:** `count` (integer, optional) — Suggestions to return; defaults to 10, clamped to 1..12; `country` (string, optional) — Google result country; defaults to us; `lang` (string, optional) — Google UI language; defaults to en; `q` (string, **required**) — Search query prefix\n\n### `google_trends_categories`\n\n- **HTTP:** `GET /google/trends/categories`\n- **What:** Google Trends categories. Returns supported top-level Google Trends category ids and labels for Trending Now category filters.\n- **Params:** _none_\n\n### `google_trends_enums`\n\n- **HTTP:** `GET /google/trends/enums`\n- **What:** Google Trends enum metadata. Returns supported Google Trends enum values for explore/trending filters, including locations, date ranges, search types, categories, statuses, and sort modes.\n- **Params:** _none_\n\n### `google_trends_explore`\n\n- **HTTP:** `POST /google/trends/explore`\n- **What:** Google Trends explore data. Returns normalized Google Trends keyword analytics from internal Trends widget requests: interest over time, interest by region, related queries, and related topics when available.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_explore_interest_by_region`\n\n- **HTTP:** `POST /google/trends/explore/interest-by-region`\n- **What:** Google Trends interest by region. Returns only the interest-by-region widget from the Google Trends Explore widget flow. Supports multiple comparison terms and returns an empty interest_by_region array when Google returns no rows.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_explore_interest_over_time`\n\n- **HTTP:** `POST /google/trends/explore/interest-over-time`\n- **What:** Google Trends interest over time. Returns only the interest-over-time timeline from the Google Trends Explore widget flow. Supports multiple comparison terms.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_explore_related_topics`\n\n- **HTTP:** `POST /google/trends/explore/related-topics`\n- **What:** Google Trends related topics. Returns only the related topics widget from the Google Trends Explore widget flow. Returns an empty related_topics array when Google returns no topic rows for the requested term/filter combination.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_explore_rising_queries`\n\n- **HTTP:** `POST /google/trends/explore/rising-queries`\n- **What:** Google Trends explore rising queries. Returns the Rising related queries widget for one or more Google Trends explore terms. Returns an empty queries array when Google returns no rows for the requested term/filter combination.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_explore_top_queries`\n\n- **HTTP:** `POST /google/trends/explore/top-queries`\n- **What:** Google Trends explore top queries. Returns the Top related queries widget for one or more Google Trends explore terms. Returns an empty queries array when Google returns no rows for the requested term/filter combination.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_locations`\n\n- **HTTP:** `GET /google/trends/locations`\n- **What:** Google Trends locations. Returns supported Google Trends location codes. Explore endpoints also accept WORLDWIDE.\n- **Params:** _none_\n\n### `google_trends_trending`\n\n- **HTTP:** `GET /google/trends/trending`\n- **What:** Google Trends trending now data. Returns normalized Google Trends Trending Now rows from the internal TrendsUi batch RPC replay.\n- **Params:** `category` (integer, optional) — Trending category id; `geo` (string, optional) — Country/territory location code; `hl` (string, optional) — Google Trends UI locale; `limit` (integer, optional) — Maximum rows to return; `sort_by` (string, optional) — Sort mode; `status` (string, optional) — Trend status filter; `time_range` (string, optional) — Alias for window; `tz` (integer, optional) — Timezone offset minutes; `window` (string, optional) — Trend window\n\n### `google_trends_trending_detail`\n\n- **HTTP:** `POST /google/trends/trending/detail`\n- **What:** Google Trends trending term detail. Returns the Explore detail widgets for a single trending term, including interest over time, regional interest, top/rising related queries, and related topics when Google returns them.\n- **Params:** `request` (object, **required**) — Trending detail request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_videos`\n\n- **HTTP:** `GET /google/videos`\n- **What:** Search Google video results. Returns normalized Google video vertical results (title, platform, link, duration, age) parsed from the public Google video results page. Locale defaults to country=us and lang=en. Returns 503 when Google serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Google UI language; defaults to en; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n## Bing (5)\n\n### `bing_images`\n\n- **HTTP:** `GET /bing/images`\n- **What:** Search Bing image results. Returns normalized Bing image search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Bing image HTML/async pages and return 503 when Bing serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Bing UI language; defaults to en-us; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n### `bing_news`\n\n- **HTTP:** `GET /bing/news`\n- **What:** Search Bing news results. Returns normalized Bing news search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Bing news HTML/async pages and return 503 when Bing serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Bing UI language; defaults to en-us; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n### `bing_search`\n\n- **HTTP:** `GET /bing/search`\n- **What:** Search Bing web results. Returns normalized Bing web search results for a query string, including organic results, optional context panel data, related queries, people-also-ask questions, news modules, video modules, and page-based pagination. Empty optional blocks are omitted from the JSON response. Locale defaults to country=us and lang=en-us. Results are fetched with a Chrome-impersonated request client and return 503 on a genuine transport failure or challenge page. Bing occasionally serves a well-formed page whose results share no significant term with the query; when every hedged attempt hits this, the response is still returned as 200 with data.low_confidence set to true (and the X-Low-Confidence header) instead of being withheld, so callers get Bing's real answer plus an honest signal to double-check it rather than nothing. Queries that use the site: operator (for example site:gov.hu) are not supported: Bing serves a bot-verification challenge for them, so they are rejected with 400 before any request is made. Use the DuckDuckGo (/api/v1/duckduckgo/search), Brave (/api/v1/brave/search), or Yahoo (/api/v1/yahoo-search/search) search endpoints for domain-restricted searches instead.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Bing UI language; defaults to en-us; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n### `bing_suggest`\n\n- **HTTP:** `GET /bing/suggest`\n- **What:** Suggest Bing search queries. Returns Bing autosuggest query completions for a query prefix. Locale defaults to country=us and lang=en-us. Suggestions are fetched from public Bing suggest endpoints and trimmed to the requested count.\n- **Params:** `count` (integer, optional) — Suggestions to return; defaults to 10, clamped to 1..12; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Bing UI language; defaults to en-us; `q` (string, **required**) — Search query prefix\n\n### `bing_videos`\n\n- **HTTP:** `GET /bing/videos`\n- **What:** Search Bing video results. Returns normalized Bing video search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Bing video HTML/async pages and return 503 when Bing serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Bing UI language; defaults to en-us; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n## Brave (5)\n\n### `brave_images`\n\n- **HTTP:** `GET /brave/images`\n- **What:** Search Brave image results. Returns normalized Brave image search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Brave Search image HTML and return 503 when Brave serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results to return; defaults to 10, clamped to 1..50; `country` (string, optional) — Brave result country; defaults to us; `lang` (string, optional) — Brave UI language; defaults to en-us; `offset` (integer, optional) — Zero-based Brave result page; defaults to 0; `q` (string, **required**) — Search query\n\n### `brave_news`\n\n- **HTTP:** `GET /brave/news`\n- **What:** Search Brave news results. Returns normalized Brave news search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Brave Search news HTML and return 503 when Brave serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results to return; defaults to 10, clamped to 1..50; `country` (string, optional) — Brave result country; defaults to us; `date_from` (string, optional) — Custom start date in YYYY-MM-DD; requires date_to; `date_to` (string, optional) — Custom end date in YYYY-MM-DD; requires date_from; `lang` (string, optional) — Brave UI language; defaults to en-us; `offset` (integer, optional) — Zero-based Brave result page; defaults to 0; `q` (string, **required**) — Search query; `time_range` (string, optional) — Preset time filter: any, day, week, month, year, or custom\n\n### `brave_search`\n\n- **HTTP:** `GET /brave/search`\n- **What:** Search Brave. Returns normalized web search results from Brave Search for a query string, along with offset-based pagination, related queries, discussions, videos, and the right-side knowledge card when Brave includes one. Use time_range for preset ranges or date_from/date_to for a custom YYYY-MM-DD range. Locale defaults to country=us and lang=en-us.\n- **Params:** `country` (string, optional) — Brave result country; defaults to us; `date_from` (string, optional) — Custom start date in YYYY-MM-DD; requires date_to; `date_to` (string, optional) — Custom end date in YYYY-MM-DD; requires date_from; `lang` (string, optional) — Brave UI language; defaults to en-us; `offset` (integer, optional) — Zero-based Brave result page; `q` (string, **required**) — Search query; `time_range` (string, optional) — Preset time filter: any, day, week, month, year, or custom\n\n### `brave_suggest`\n\n- **HTTP:** `GET /brave/suggest`\n- **What:** Suggest Brave search queries. Returns Brave autosuggest query completions for a query prefix. Locale defaults to country=us and lang=en-us. Suggestions are fetched from public Brave Search suggest JSON and trimmed to the requested count.\n- **Params:** `count` (integer, optional) — Suggestions to return; defaults to 10, clamped to 1..12; `country` (string, optional) — Brave result country; defaults to us; `lang` (string, optional) — Brave UI language; defaults to en-us; `q` (string, **required**) — Search query prefix\n\n### `brave_videos`\n\n- **HTTP:** `GET /brave/videos`\n- **What:** Search Brave video results. Returns normalized Brave video search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Brave Search video HTML and return 503 when Brave serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results to return; defaults to 10, clamped to 1..50; `country` (string, optional) — Brave result country; defaults to us; `date_from` (string, optional) — Custom start date in YYYY-MM-DD; requires date_to; `date_to` (string, optional) — Custom end date in YYYY-MM-DD; requires date_from; `lang` (string, optional) — Brave UI language; defaults to en-us; `offset` (integer, optional) — Zero-based Brave result page; defaults to 0; `q` (string, **required**) — Search query; `time_range` (string, optional) — Preset time filter: any, day, week, month, year, or custom\n\n## DuckDuckGo Search (5)\n\n### `duckduckgo_image`\n\n- **HTTP:** `GET /duckduckgo/image`\n- **What:** Search DuckDuckGo image results. Returns normalized DuckDuckGo image results for a query string: title, source page URL, image URL, thumbnail, dimensions, and hostname, plus page-based pagination. Results are fetched from DuckDuckGo's own image JSON API.\n- **Params:** `page` (integer, optional) — 1-based page number, defaults to 1; `q` (string, **required**) — Search query; `region` (string, optional) — DuckDuckGo region/locale code, e.g. us-en, uk-en, wt-wt (worldwide, the default)\n\n### `duckduckgo_news`\n\n- **HTTP:** `GET /duckduckgo/news`\n- **What:** Search DuckDuckGo news results. Returns normalized DuckDuckGo news results for a query string: title, destination URL, source, excerpt, thumbnail, and relative/published time, plus page-based pagination. Results are fetched from DuckDuckGo's own news JSON API.\n- **Params:** `page` (integer, optional) — 1-based page number, defaults to 1; `q` (string, **required**) — Search query; `region` (string, optional) — DuckDuckGo region/locale code, e.g. us-en, uk-en, wt-wt (worldwide, the default)\n\n### `duckduckgo_search`\n\n- **HTTP:** `GET /duckduckgo/search`\n- **What:** Search DuckDuckGo web results. Returns normalized DuckDuckGo web search results for a query string: title, destination URL, description, and hostname, plus page-based pagination. DuckDuckGo wraps every result link in its own click-tracking redirect; this endpoint always returns the decoded destination URL, never the raw redirect link. Results are fetched from DuckDuckGo's own server-rendered search page.\n- **Params:** `page` (integer, optional) — 1-based page number, defaults to 1; `q` (string, **required**) — Search query; `region` (string, optional) — DuckDuckGo region/locale code, e.g. us-en, uk-en, wt-wt (worldwide, the default); `safe_search` (string, optional) — Safe search level, defaults to DuckDuckGo's own moderate setting when omitted; `time_range` (string, optional) — Restrict results to a recency window\n\n### `duckduckgo_shopping`\n\n- **HTTP:** `GET /duckduckgo/shopping`\n- **What:** Search DuckDuckGo shopping results. Returns normalized DuckDuckGo shopping results for a query string: title, brand, merchant, description, price, rating, and review count, plus total page count. DuckDuckGo's shopping vertical is ad-funded, syndicated product listings, not organic content; every product link is wrapped in an ad-click-tracking redirect with no clean destination to unwrap, so no destination URL is returned. DuckDuckGo's own pagination token for this vertical is an opaque per-response blob rather than a plain page offset, so only the first page is supported.\n- **Params:** `q` (string, **required**) — Search query; `region` (string, optional) — DuckDuckGo market code, e.g. us-en, uk-en\n\n### `duckduckgo_video`\n\n- **HTTP:** `GET /duckduckgo/video`\n- **What:** Search DuckDuckGo video results. Returns normalized DuckDuckGo video results for a query string: title, destination URL, description, duration, thumbnail, publisher/uploader, published time, and view count, plus page-based pagination. Results are fetched from DuckDuckGo's own video JSON API.\n- **Params:** `page` (integer, optional) — 1-based page number, defaults to 1; `q` (string, **required**) — Search query; `region` (string, optional) — DuckDuckGo region/locale code, e.g. us-en, uk-en, wt-wt (worldwide, the default)\n\n## Yahoo Search (6)\n\n### `yahoo_search`\n\n- **HTTP:** `GET /yahoo-search/search`\n- **What:** Search Yahoo web results. Returns normalized Yahoo web search results for a query string: title, destination URL, description, and hostname, plus page-based pagination. Yahoo wraps every result link in its own click-tracking redirect; this endpoint always returns the decoded destination URL, never the raw redirect link. Results are fetched from Yahoo's own server-rendered search page.\n- **Params:** `page` (integer, optional) — 1-based page number, defaults to 1; `q` (string, **required**) — Search query; `time_range` (string, optional) — Restrict results by recency. Omit for unfiltered ('Anytime').\n\n### `yahoo_search_images`\n\n- **HTTP:** `GET /yahoo-search/images`\n- **What:** Search Yahoo image results. Returns Yahoo's image-search results for a query: title, direct image URL, the page hosting the image, source domain, thumbnail, and original image dimensions when available. Results are fetched from Yahoo's own server-rendered image-search page.\n- **Params:** `q` (string, **required**) — Search query\n\n### `yahoo_search_local`\n\n- **HTTP:** `GET /yahoo-search/local`\n- **What:** Search Yahoo local business results. Returns Yahoo's local-business-search results for a query: name, category, price range, address, phone, open status, rating, and review count. Location is resolved from the query text itself, the same way a user would type into Yahoo's own local search box (e.g. \"pizza near seattle wa\"), not a separate coordinate parameter. Results are fetched from Yahoo's own server-rendered local-search page.\n- **Params:** `q` (string, **required**) — Search query, including any location intent\n\n### `yahoo_search_news`\n\n- **HTTP:** `GET /yahoo-search/news`\n- **What:** Search Yahoo news results. Returns Yahoo's news-search results for a query: title, destination URL, description, source, and relative publish age. Results are fetched from Yahoo's own server-rendered news-search page (news.search.yahoo.com) -- a distinct product from the yahoo-news family, which covers the www.yahoo.com/news portal itself. Yahoo wraps every result link in its own click-tracking redirect; this endpoint always returns the decoded destination URL, never the raw redirect link.\n- **Params:** `q` (string, **required**) — Search query\n\n### `yahoo_search_suggest`\n\n- **HTTP:** `GET /yahoo-search/suggest`\n- **What:** Yahoo web search autocomplete suggestions. Returns Yahoo's own search-box autocomplete suggestions for a partial query: a flat list of suggested search terms, each optionally carrying knowledge-panel entity metadata (type, image, subtitle, description) when Yahoo resolves the term to a known company, place, product, or similar entity rather than a plain phrase.\n- **Params:** `count` (integer, optional) — Number of suggestions to return, default 10, clamped to 1..20; `q` (string, **required**) — Partial search query to autocomplete\n\n### `yahoo_search_videos`\n\n- **HTTP:** `GET /yahoo-search/videos`\n- **What:** Search Yahoo video results. Returns Yahoo's video-search results for a query: title, destination page URL, source domain, description, thumbnail, and duration. Results are fetched from Yahoo's own server-rendered video-search page.\n- **Params:** `q` (string, **required**) — Search query\n\nFile v1.0.20:skill-card.md\n\n## Description:\n\nRuns SERP and keyword research through the Crawlora API for Google, Bing, Brave, DuckDuckGo, Yahoo, and Google Trends, returning clean JSON for rankings, SERP snapshots, keyword suggestions, and trend data.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[crawlora-org](https://clawhub.ai/user/crawlora-org)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers, SEO analysts, and research agents use this skill to collect search-engine rankings, SERP snapshots, keyword suggestions, and Google Trends signals as normalized JSON through Crawlora.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Search terms, trend requests, and the Crawlora API key are sent to Crawlora's API.\n\nMitigation: Use the skill only for queries and credentials that are acceptable under Crawlora's privacy and retention practices, and avoid confidential research terms unless those practices meet the user's requirements.\n\nRisk: A missing or invalid Crawlora API key prevents API requests from succeeding.\n\nMitigation: Set CRAWLORA_API_KEY in the environment before use and keep the key out of prompts, command arguments, committed files, and query parameters.\n\nRisk: Some search endpoints may return rate-limit, challenge, or unsupported-route responses.\n\nMitigation: Retry within documented limits, switch to another supported search engine endpoint when appropriate, and consult the bundled endpoint reference for supported routes.\n\n## Reference(s):\n\n- [Endpoint reference](reference/endpoints.md)\n- [Crawlora](https://crawlora.net)\n- [ClawHub skill page](https://clawhub.ai/crawlora-org/skills/serp-keyword-research)\n\n## Skill Output:\n\n**Output Type(s):** [Shell commands, JSON, Configuration, Guidance]\n\n**Output Format:** [Markdown guidance with shell commands and JSON API responses]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Requires CRAWLORA_API_KEY and sends public search terms and trend requests to Crawlora's API.]\n\n## Skill Version(s):\n\n1.0.20 (source: ClawHub release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.0.19: 5 files, 10769 bytes\n\nFiles: reference/endpoints.md (23355b), scripts/crawlora.sh (7789b), skill-card.md (1955b), SKILL.md (4420b), _meta.json (141b)\n\nFile v1.0.19:SKILL.md\n\n---\nname: serp-keyword-research\ndescription: Runs SERP and keyword research via the Crawlora API — Google, Bing, Brave, DuckDuckGo, and Yahoo search results plus Google Trends interest-over-time and related/rising queries — returning clean JSON. Use when the user wants search-engine rankings, SERP snapshots, autocomplete/keyword suggestions, or trend data instead of scraping result pages.\n---\n\n# SERP & keyword research\n\nCapture search-engine results (Google, Bing, Brave, DuckDuckGo, Yahoo) and\nkeyword/trend signals (Google autosuggest, Google Trends) as normalized\nJSON from the Crawlora API.\n\n## When to use this skill\n\n- \"What ranks for <query> on Google / Bing?\" / \"snapshot the SERP for …\".\n- \"Keyword ideas / autocomplete for …\" (suggest endpoints).\n- \"Is <topic> trending?\" / \"interest over time / by region for <keyword>.\"\n- \"Related and rising queries for …\" (Google Trends).\n- SEO/SERP monitoring, keyword discovery, or trend research.\n\n## Setup (one-time)\n\n- Get a free Crawlora API key (2,000 credits/mo, no card) at [https://crawlora.net](https://crawlora.net?utm_source=github&utm_medium=referral&utm_campaign=crawlora-skills).\n- Set `CRAWLORA_API_KEY` in the environment before running the helper.\n- The helper reads `CRAWLORA_API_KEY` from the environment and sends requests to `https://api.crawlora.net/api/v1`. Missing/invalid key → `401`.\n\n## How it works\n\n1. **SERP** — Google search is `POST /google/search` with flat `keyword`, `language`, and `country` fields;\n   Bing, Brave, DuckDuckGo, and Yahoo are plain `GET` with `q`:\n   `/bing/search`, `/brave/search`, `/duckduckgo/search`, `/yahoo-search/search`.\n   Cross-check engines for coverage; on a `503` challenge, fall back to another engine.\n2. **Verticals** — news/videos/images per engine (`/google/news`, `/bing/videos`,\n   `/duckduckgo/news`, `/duckduckgo/image`, `/duckduckgo/video`, `/duckduckgo/shopping`, …).\n3. **Keyword ideas** — autosuggest: `GET /google/suggest?q=...` (and `/bing/suggest`,\n   `/brave/suggest`).\n4. **Trends** — Google Trends `POST` endpoints:\n   `/google/trends/explore/interest-over-time`, `/interest-by-region`,\n   `/related-topics`, `/rising-queries`, `/top-queries` (body: `{\"keywords\":[...]}`),\n   plus `GET /google/trends/trending` for what's hot now.\n\nFull endpoint list, methods, and params: [`reference/endpoints.md`](reference/endpoints.md).\n\n## Calling the API\n\n```sh\n# GET search engines + suggest:\nscripts/crawlora.sh /bing/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /brave/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /duckduckgo/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /yahoo-search/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /google/suggest q=\"web scraping\" | jq '.'\n\n# POST endpoints take a JSON body (note -X POST):\nscripts/crawlora.sh -X POST /google/search '{\"keyword\":\"web scraping api\",\"language\":\"en\",\"country\":\"us\"}' | jq '.'\nscripts/crawlora.sh -X POST /google/trends/explore/interest-over-time '{\"keywords\":[\"web scraping\"]}' | jq '.'\n```\n\nUse `scripts/crawlora.sh` for all requests; it keeps the API key out of command-line arguments.\n\n\n## Endpoint reference\n\nSee [`reference/endpoints.md`](reference/endpoints.md) for every Google, Bing,\nBrave, DuckDuckGo, Yahoo, and Google Trends endpoint this skill uses (method,\npath, params, description).\n\n## Examples\n\n- **SERP snapshot:** `POST /google/search` (and `/bing/search`) for a target query;\n  record the ranked result titles/URLs to track positions over time.\n- **Keyword expansion:** seed term → `/google/suggest` → for each suggestion,\n  `POST /google/trends/explore/rising-queries` to find momentum.\n- **Trend check:** `POST /google/trends/explore/interest-over-time` with\n  `{\"keywords\":[\"electric bikes\",\"e-bikes\"]}` and compare the series.\n\n## Notes & limits\n\n- **Credits / pay-on-success:** billed only on `2xx`; free tier 2,000 credits/mo.\n  Key at [https://crawlora.net](https://crawlora.net?utm_source=github&utm_medium=referral&utm_campaign=crawlora-skills).\n- **Public data only** — public search results; respect each engine's terms.\n- **Security:** key lives in `CRAWLORA_API_KEY` only — never hardcode, query-param, or commit it.\n- Search endpoints may return `503` when the engine serves a challenge page —\n  retry or switch engines (Google ↔ Bing ↔ Brave). Google search is rate-limited\n  to ~1 req/s (`429` on excess).\n\nFile v1.0.19:_meta.json\n\n{\n  \"ownerId\": \"kn70shhkf6qpfwgfrbgtep2wkd8c6b4t\",\n  \"slug\": \"serp-keyword-research\",\n  \"version\": \"1.0.19\",\n  \"publishedAt\": 1789640439260\n}\n\nFile v1.0.19:reference/endpoints.md\n\n# serp-keyword-research — endpoint reference\n\n> Generated from `scripts/tools.json` by `scripts/generate.mjs` — do not edit by hand.\n\nEndpoints this skill uses, grouped by platform. Call them via `scripts/crawlora.sh` (see SKILL.md).\n\nAll paths are relative to the API base `https://api.crawlora.net/api/v1` and require the header `x-api-key: $CRAWLORA_API_KEY`. Path params like `{id}` are substituted into the URL; `GET` params go in the query string; `POST` params go in a JSON body.\n\n**36 endpoints across 5 platform group(s).**\n\n## Google (15)\n\n### `google_news`\n\n- **HTTP:** `GET /google/news`\n- **What:** Search Google News. Returns normalized Google News vertical results (title, source, link, age) parsed from the public Google News results page. Locale defaults to country=us and lang=en. Returns 503 when Google serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Google UI language; defaults to en; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n### `google_search`\n\n- **HTTP:** `POST /google/search`\n- **What:** Google search API. Returns normalized Google web search results. Results are fetched through proxied browser renderers that race several concurrent renders per request and return the first clean result, with stale-cache fallback when available. The endpoint returns 503 when Google serves a challenge page or unusable HTML. Rate limit is enforced at 1 request per second, and if the limit is exceeded a 429 status code is returned with rate limit headers.\n- **Params:** `searchOption` (object, **required**) — Search options\n- **REST body:** Send the value of the MCP argument `searchOption` directly as the JSON body; do not wrap it in a `searchOption` property.\n\n### `google_suggest`\n\n- **HTTP:** `GET /google/suggest`\n- **What:** Suggest Google search queries. Returns Google autosuggest query completions from the public unauthenticated suggest JSON endpoint.\n- **Params:** `count` (integer, optional) — Suggestions to return; defaults to 10, clamped to 1..12; `country` (string, optional) — Google result country; defaults to us; `lang` (string, optional) — Google UI language; defaults to en; `q` (string, **required**) — Search query prefix\n\n### `google_trends_categories`\n\n- **HTTP:** `GET /google/trends/categories`\n- **What:** Google Trends categories. Returns supported top-level Google Trends category ids and labels for Trending Now category filters.\n- **Params:** _none_\n\n### `google_trends_enums`\n\n- **HTTP:** `GET /google/trends/enums`\n- **What:** Google Trends enum metadata. Returns supported Google Trends enum values for explore/trending filters, including locations, date ranges, search types, categories, statuses, and sort modes.\n- **Params:** _none_\n\n### `google_trends_explore`\n\n- **HTTP:** `POST /google/trends/explore`\n- **What:** Google Trends explore data. Returns normalized Google Trends keyword analytics from internal Trends widget requests: interest over time, interest by region, related queries, and related topics when available.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_explore_interest_by_region`\n\n- **HTTP:** `POST /google/trends/explore/interest-by-region`\n- **What:** Google Trends interest by region. Returns only the interest-by-region widget from the Google Trends Explore widget flow. Supports multiple comparison terms and returns an empty interest_by_region array when Google returns no rows.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_explore_interest_over_time`\n\n- **HTTP:** `POST /google/trends/explore/interest-over-time`\n- **What:** Google Trends interest over time. Returns only the interest-over-time timeline from the Google Trends Explore widget flow. Supports multiple comparison terms.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_explore_related_topics`\n\n- **HTTP:** `POST /google/trends/explore/related-topics`\n- **What:** Google Trends related topics. Returns only the related topics widget from the Google Trends Explore widget flow. Returns an empty related_topics array when Google returns no topic rows for the requested term/filter combination.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_explore_rising_queries`\n\n- **HTTP:** `POST /google/trends/explore/rising-queries`\n- **What:** Google Trends explore rising queries. Returns the Rising related queries widget for one or more Google Trends explore terms. Returns an empty queries array when Google returns no rows for the requested term/filter combination.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_explore_top_queries`\n\n- **HTTP:** `POST /google/trends/explore/top-queries`\n- **What:** Google Trends explore top queries. Returns the Top related queries widget for one or more Google Trends explore terms. Returns an empty queries array when Google returns no rows for the requested term/filter combination.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_locations`\n\n- **HTTP:** `GET /google/trends/locations`\n- **What:** Google Trends locations. Returns supported Google Trends location codes. Explore endpoints also accept WORLDWIDE.\n- **Params:** _none_\n\n### `google_trends_trending`\n\n- **HTTP:** `GET /google/trends/trending`\n- **What:** Google Trends trending now data. Returns normalized Google Trends Trending Now rows from the internal TrendsUi batch RPC replay.\n- **Params:** `category` (integer, optional) — Trending category id; `geo` (string, optional) — Country/territory location code; `hl` (string, optional) — Google Trends UI locale; `limit` (integer, optional) — Maximum rows to return; `sort_by` (string, optional) — Sort mode; `status` (string, optional) — Trend status filter; `time_range` (string, optional) — Alias for window; `tz` (integer, optional) — Timezone offset minutes; `window` (string, optional) — Trend window\n\n### `google_trends_trending_detail`\n\n- **HTTP:** `POST /google/trends/trending/detail`\n- **What:** Google Trends trending term detail. Returns the Explore detail widgets for a single trending term, including interest over time, regional interest, top/rising related queries, and related topics when Google returns them.\n- **Params:** `request` (object, **required**) — Trending detail request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_videos`\n\n- **HTTP:** `GET /google/videos`\n- **What:** Search Google video results. Returns normalized Google video vertical results (title, platform, link, duration, age) parsed from the public Google video results page. Locale defaults to country=us and lang=en. Returns 503 when Google serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Google UI language; defaults to en; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n## Bing (5)\n\n### `bing_images`\n\n- **HTTP:** `GET /bing/images`\n- **What:** Search Bing image results. Returns normalized Bing image search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Bing image HTML/async pages and return 503 when Bing serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Bing UI language; defaults to en-us; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n### `bing_news`\n\n- **HTTP:** `GET /bing/news`\n- **What:** Search Bing news results. Returns normalized Bing news search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Bing news HTML/async pages and return 503 when Bing serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Bing UI language; defaults to en-us; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n### `bing_search`\n\n- **HTTP:** `GET /bing/search`\n- **What:** Search Bing web results. Returns normalized Bing web search results for a query string, including organic results, optional context panel data, related queries, people-also-ask questions, news modules, video modules, and page-based pagination. Empty optional blocks are omitted from the JSON response. Locale defaults to country=us and lang=en-us. Results are fetched with a Chrome-impersonated request client and return 503 on a genuine transport failure or challenge page. Bing occasionally serves a well-formed page whose results share no significant term with the query; when every hedged attempt hits this, the response is still returned as 200 with data.low_confidence set to true (and the X-Low-Confidence header) instead of being withheld, so callers get Bing's real answer plus an honest signal to double-check it rather than nothing. Queries that use the site: operator (for example site:gov.hu) are not supported: Bing serves a bot-verification challenge for them, so they are rejected with 400 before any request is made. Use the Google search endpoint (/api/v1/google/search) for domain-restricted searches.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Bing UI language; defaults to en-us; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n### `bing_suggest`\n\n- **HTTP:** `GET /bing/suggest`\n- **What:** Suggest Bing search queries. Returns Bing autosuggest query completions for a query prefix. Locale defaults to country=us and lang=en-us. Suggestions are fetched from public Bing suggest endpoints and trimmed to the requested count.\n- **Params:** `count` (integer, optional) — Suggestions to return; defaults to 10, clamped to 1..12; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Bing UI language; defaults to en-us; `q` (string, **required**) — Search query prefix\n\n### `bing_videos`\n\n- **HTTP:** `GET /bing/videos`\n- **What:** Search Bing video results. Returns normalized Bing video search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Bing video HTML/async pages and return 503 when Bing serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Bing UI language; defaults to en-us; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n## Brave (5)\n\n### `brave_images`\n\n- **HTTP:** `GET /brave/images`\n- **What:** Search Brave image results. Returns normalized Brave image search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Brave Search image HTML and return 503 when Brave serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results to return; defaults to 10, clamped to 1..50; `country` (string, optional) — Brave result country; defaults to us; `lang` (string, optional) — Brave UI language; defaults to en-us; `offset` (integer, optional) — Zero-based Brave result page; defaults to 0; `q` (string, **required**) — Search query\n\n### `brave_news`\n\n- **HTTP:** `GET /brave/news`\n- **What:** Search Brave news results. Returns normalized Brave news search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Brave Search news HTML and return 503 when Brave serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results to return; defaults to 10, clamped to 1..50; `country` (string, optional) — Brave result country; defaults to us; `date_from` (string, optional) — Custom start date in YYYY-MM-DD; requires date_to; `date_to` (string, optional) — Custom end date in YYYY-MM-DD; requires date_from; `lang` (string, optional) — Brave UI language; defaults to en-us; `offset` (integer, optional) — Zero-based Brave result page; defaults to 0; `q` (string, **required**) — Search query; `time_range` (string, optional) — Preset time filter: any, day, week, month, year, or custom\n\n### `brave_search`\n\n- **HTTP:** `GET /brave/search`\n- **What:** Search Brave. Returns normalized web search results from Brave Search for a query string, along with offset-based pagination, related queries, discussions, videos, and the right-side knowledge card when Brave includes one. Use time_range for preset ranges or date_from/date_to for a custom YYYY-MM-DD range. Locale defaults to country=us and lang=en-us.\n- **Params:** `country` (string, optional) — Brave result country; defaults to us; `date_from` (string, optional) — Custom start date in YYYY-MM-DD; requires date_to; `date_to` (string, optional) — Custom end date in YYYY-MM-DD; requires date_from; `lang` (string, optional) — Brave UI language; defaults to en-us; `offset` (integer, optional) — Zero-based Brave result page; `q` (string, **required**) — Search query; `time_range` (string, optional) — Preset time filter: any, day, week, month, year, or custom\n\n### `brave_suggest`\n\n- **HTTP:** `GET /brave/suggest`\n- **What:** Suggest Brave search queries. Returns Brave autosuggest query completions for a query prefix. Locale defaults to country=us and lang=en-us. Suggestions are fetched from public Brave Search suggest JSON and trimmed to the requested count.\n- **Params:** `count` (integer, optional) — Suggestions to return; defaults to 10, clamped to 1..12; `country` (string, optional) — Brave result country; defaults to us; `lang` (string, optional) — Brave UI language; defaults to en-us; `q` (string, **required**) — Search query prefix\n\n### `brave_videos`\n\n- **HTTP:** `GET /brave/videos`\n- **What:** Search Brave video results. Returns normalized Brave video search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Brave Search video HTML and return 503 when Brave serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results to return; defaults to 10, clamped to 1..50; `country` (string, optional) — Brave result country; defaults to us; `date_from` (string, optional) — Custom start date in YYYY-MM-DD; requires date_to; `date_to` (string, optional) — Custom end date in YYYY-MM-DD; requires date_from; `lang` (string, optional) — Brave UI language; defaults to en-us; `offset` (integer, optional) — Zero-based Brave result page; defaults to 0; `q` (string, **required**) — Search query; `time_range` (string, optional) — Preset time filter: any, day, week, month, year, or custom\n\n## DuckDuckGo Search (5)\n\n### `duckduckgo_image`\n\n- **HTTP:** `GET /duckduckgo/image`\n- **What:** Search DuckDuckGo image results. Returns normalized DuckDuckGo image results for a query string: title, source page URL, image URL, thumbnail, dimensions, and hostname, plus page-based pagination. Results are fetched from DuckDuckGo's own image JSON API.\n- **Params:** `page` (integer, optional) — 1-based page number, defaults to 1; `q` (string, **required**) — Search query; `region` (string, optional) — DuckDuckGo region/locale code, e.g. us-en, uk-en, wt-wt (worldwide, the default)\n\n### `duckduckgo_news`\n\n- **HTTP:** `GET /duckduckgo/news`\n- **What:** Search DuckDuckGo news results. Returns normalized DuckDuckGo news results for a query string: title, destination URL, source, excerpt, thumbnail, and relative/published time, plus page-based pagination. Results are fetched from DuckDuckGo's own news JSON API.\n- **Params:** `page` (integer, optional) — 1-based page number, defaults to 1; `q` (string, **required**) — Search query; `region` (string, optional) — DuckDuckGo region/locale code, e.g. us-en, uk-en, wt-wt (worldwide, the default)\n\n### `duckduckgo_search`\n\n- **HTTP:** `GET /duckduckgo/search`\n- **What:** Search DuckDuckGo web results. Returns normalized DuckDuckGo web search results for a query string: title, destination URL, description, and hostname, plus page-based pagination. DuckDuckGo wraps every result link in its own click-tracking redirect; this endpoint always returns the decoded destination URL, never the raw redirect link. Results are fetched from DuckDuckGo's own server-rendered search page.\n- **Params:** `page` (integer, optional) — 1-based page number, defaults to 1; `q` (string, **required**) — Search query; `region` (string, optional) — DuckDuckGo region/locale code, e.g. us-en, uk-en, wt-wt (worldwide, the default); `safe_search` (string, optional) — Safe search level, defaults to DuckDuckGo's own moderate setting when omitted; `time_range` (string, optional) — Restrict results to a recency window\n\n### `duckduckgo_shopping`\n\n- **HTTP:** `GET /duckduckgo/shopping`\n- **What:** Search DuckDuckGo shopping results. Returns normalized DuckDuckGo shopping results for a query string: title, brand, merchant, description, price, rating, and review count, plus total page count. DuckDuckGo's shopping vertical is ad-funded, syndicated product listings, not organic content; every product link is wrapped in an ad-click-tracking redirect with no clean destination to unwrap, so no destination URL is returned. DuckDuckGo's own pagination token for this vertical is an opaque per-response blob rather than a plain page offset, so only the first page is supported.\n- **Params:** `q` (string, **required**) — Search query; `region` (string, optional) — DuckDuckGo market code, e.g. us-en, uk-en\n\n### `duckduckgo_video`\n\n- **HTTP:** `GET /duckduckgo/video`\n- **What:** Search DuckDuckGo video results. Returns normalized DuckDuckGo video results for a query string: title, destination URL, description, duration, thumbnail, publisher/uploader, published time, and view count, plus page-based pagination. Results are fetched from DuckDuckGo's own video JSON API.\n- **Params:** `page` (integer, optional) — 1-based page number, defaults to 1; `q` (string, **required**) — Search query; `region` (string, optional) — DuckDuckGo region/locale code, e.g. us-en, uk-en, wt-wt (worldwide, the default)\n\n## Yahoo Search (6)\n\n### `yahoo_search`\n\n- **HTTP:** `GET /yahoo-search/search`\n- **What:** Search Yahoo web results. Returns normalized Yahoo web search results for a query string: title, destination URL, description, and hostname, plus page-based pagination. Yahoo wraps every result link in its own click-tracking redirect; this endpoint always returns the decoded destination URL, never the raw redirect link. Results are fetched from Yahoo's own server-rendered search page.\n- **Params:** `page` (integer, optional) — 1-based page number, defaults to 1; `q` (string, **required**) — Search query; `time_range` (string, optional) — Restrict results by recency. Omit for unfiltered ('Anytime').\n\n### `yahoo_search_images`\n\n- **HTTP:** `GET /yahoo-search/images`\n- **What:** Search Yahoo image results. Returns Yahoo's image-search results for a query: title, direct image URL, the page hosting the image, source domain, thumbnail, and original image dimensions when available. Results are fetched from Yahoo's own server-rendered image-search page.\n- **Params:** `q` (string, **required**) — Search query\n\n### `yahoo_search_local`\n\n- **HTTP:** `GET /yahoo-search/local`\n- **What:** Search Yahoo local business results. Returns Yahoo's local-business-search results for a query: name, category, price range, address, phone, open status, rating, and review count. Location is resolved from the query text itself, the same way a user would type into Yahoo's own local search box (e.g. \"pizza near seattle wa\"), not a separate coordinate parameter. Results are fetched from Yahoo's own server-rendered local-search page.\n- **Params:** `q` (string, **required**) — Search query, including any location intent\n\n### `yahoo_search_news`\n\n- **HTTP:** `GET /yahoo-search/news`\n- **What:** Search Yahoo news results. Returns Yahoo's news-search results for a query: title, destination URL, description, source, and relative publish age. Results are fetched from Yahoo's own server-rendered news-search page (news.search.yahoo.com) -- a distinct product from the yahoo-news family, which covers the www.yahoo.com/news portal itself. Yahoo wraps every result link in its own click-tracking redirect; this endpoint always returns the decoded destination URL, never the raw redirect link.\n- **Params:** `q` (string, **required**) — Search query\n\n### `yahoo_search_suggest`\n\n- **HTTP:** `GET /yahoo-search/suggest`\n- **What:** Yahoo web search autocomplete suggestions. Returns Yahoo's own search-box autocomplete suggestions for a partial query: a flat list of suggested search terms, each optionally carrying knowledge-panel entity metadata (type, image, subtitle, description) when Yahoo resolves the term to a known company, place, product, or similar entity rather than a plain phrase.\n- **Params:** `count` (integer, optional) — Number of suggestions to return, default 10, clamped to 1..20; `q` (string, **required**) — Partial search query to autocomplete\n\n### `yahoo_search_videos`\n\n- **HTTP:** `GET /yahoo-search/videos`\n- **What:** Search Yahoo video results. Returns Yahoo's video-search results for a query: title, destination page URL, source domain, description, thumbnail, and duration. Results are fetched from Yahoo's own server-rendered video-search page.\n- **Params:** `q` (string, **required**) — Search query\n\nFile v1.0.19:skill-card.md\n\n## Description:\n\nRuns SERP and keyword research via the Crawlora API, covering Google, Bing, Brave, DuckDuckGo, Yahoo, and Google Trends signals, and returns normalized JSON.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[crawlora-org](https://clawhub.ai/user/crawlora-org)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers, SEO practitioners, and research analysts use this skill to collect search result snapshots, keyword suggestions, and Google Trends signals through Crawlora instead of scraping search result pages directly.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Search terms, trend terms, and request bodies are sent to Crawlora and may be used to query upstream search services.\n\nMitigation: Avoid confidential names, secrets, regulated personal data, or private investigation terms unless that external sharing is acceptable.\n\nRisk: The skill requires a Crawlora API key to call the external API.\n\nMitigation: Keep the key in the CRAWLORA_API_KEY environment variable and do not hardcode it, commit it, or place it in prompts or query parameters.\n\n## Reference(s):\n\n- [Endpoint reference](reference/endpoints.md)\n- [Crawlora](https://crawlora.net)\n- [ClawHub skill page](https://clawhub.ai/crawlora-org/skills/serp-keyword-research)\n\n## Skill Output:\n\n**Output Type(s):** [JSON, Shell commands, Guidance]\n\n**Output Format:** [Markdown guidance with shell commands and JSON API responses]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Requires a Crawlora API key in the CRAWLORA_API_KEY environment variable.]\n\n## Skill Version(s):\n\n1.0.19 (source: server release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.0.18: 5 files, 10815 bytes\n\nFiles: reference/endpoints.md (23355b), scripts/crawlora.sh (7164b), skill-card.md (2453b), SKILL.md (4420b), _meta.json (141b)\n\nFile v1.0.18:SKILL.md\n\n---\nname: serp-keyword-research\ndescription: Runs SERP and keyword research via the Crawlora API — Google, Bing, Brave, DuckDuckGo, and Yahoo search results plus Google Trends interest-over-time and related/rising queries — returning clean JSON. Use when the user wants search-engine rankings, SERP snapshots, autocomplete/keyword suggestions, or trend data instead of scraping result pages.\n---\n\n# SERP & keyword research\n\nCapture search-engine results (Google, Bing, Brave, DuckDuckGo, Yahoo) and\nkeyword/trend signals (Google autosuggest, Google Trends) as normalized\nJSON from the Crawlora API.\n\n## When to use this skill\n\n- \"What ranks for <query> on Google / Bing?\" / \"snapshot the SERP for …\".\n- \"Keyword ideas / autocomplete for …\" (suggest endpoints).\n- \"Is <topic> trending?\" / \"interest over time / by region for <keyword>.\"\n- \"Related and rising queries for …\" (Google Trends).\n- SEO/SERP monitoring, keyword discovery, or trend research.\n\n## Setup (one-time)\n\n- Get a free Crawlora API key (2,000 credits/mo, no card) at [https://crawlora.net](https://crawlora.net?utm_source=github&utm_medium=referral&utm_campaign=crawlora-skills).\n- Set `CRAWLORA_API_KEY` in the environment before running the helper.\n- The helper reads `CRAWLORA_API_KEY` from the environment and sends requests to `https://api.crawlora.net/api/v1`. Missing/invalid key → `401`.\n\n## How it works\n\n1. **SERP** — Google search is `POST /google/search` with flat `keyword`, `language`, and `country` fields;\n   Bing, Brave, DuckDuckGo, and Yahoo are plain `GET` with `q`:\n   `/bing/search`, `/brave/search`, `/duckduckgo/search`, `/yahoo-search/search`.\n   Cross-check engines for coverage; on a `503` challenge, fall back to another engine.\n2. **Verticals** — news/videos/images per engine (`/google/news`, `/bing/videos`,\n   `/duckduckgo/news`, `/duckduckgo/image`, `/duckduckgo/video`, `/duckduckgo/shopping`, …).\n3. **Keyword ideas** — autosuggest: `GET /google/suggest?q=...` (and `/bing/suggest`,\n   `/brave/suggest`).\n4. **Trends** — Google Trends `POST` endpoints:\n   `/google/trends/explore/interest-over-time`, `/interest-by-region`,\n   `/related-topics`, `/rising-queries`, `/top-queries` (body: `{\"keywords\":[...]}`),\n   plus `GET /google/trends/trending` for what's hot now.\n\nFull endpoint list, methods, and params: [`reference/endpoints.md`](reference/endpoints.md).\n\n## Calling the API\n\n```sh\n# GET search engines + suggest:\nscripts/crawlora.sh /bing/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /brave/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /duckduckgo/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /yahoo-search/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /google/suggest q=\"web scraping\" | jq '.'\n\n# POST endpoints take a JSON body (note -X POST):\nscripts/crawlora.sh -X POST /google/search '{\"keyword\":\"web scraping api\",\"language\":\"en\",\"country\":\"us\"}' | jq '.'\nscripts/crawlora.sh -X POST /google/trends/explore/interest-over-time '{\"keywords\":[\"web scraping\"]}' | jq '.'\n```\n\nUse `scripts/crawlora.sh` for all requests; it keeps the API key out of command-line arguments.\n\n\n## Endpoint reference\n\nSee [`reference/endpoints.md`](reference/endpoints.md) for every Google, Bing,\nBrave, DuckDuckGo, Yahoo, and Google Trends endpoint this skill uses (method,\npath, params, description).\n\n## Examples\n\n- **SERP snapshot:** `POST /google/search` (and `/bing/search`) for a target query;\n  record the ranked result titles/URLs to track positions over time.\n- **Keyword expansion:** seed term → `/google/suggest` → for each suggestion,\n  `POST /google/trends/explore/rising-queries` to find momentum.\n- **Trend check:** `POST /google/trends/explore/interest-over-time` with\n  `{\"keywords\":[\"electric bikes\",\"e-bikes\"]}` and compare the series.\n\n## Notes & limits\n\n- **Credits / pay-on-success:** billed only on `2xx`; free tier 2,000 credits/mo.\n  Key at [https://crawlora.net](https://crawlora.net?utm_source=github&utm_medium=referral&utm_campaign=crawlora-skills).\n- **Public data only** — public search results; respect each engine's terms.\n- **Security:** key lives in `CRAWLORA_API_KEY` only — never hardcode, query-param, or commit it.\n- Search endpoints may return `503` when the engine serves a challenge page —\n  retry or switch engines (Google ↔ Bing ↔ Brave). Google search is rate-limited\n  to ~1 req/s (`429` on excess).\n\nFile v1.0.18:_meta.json\n\n{\n  \"ownerId\": \"kn70shhkf6qpfwgfrbgtep2wkd8c6b4t\",\n  \"slug\": \"serp-keyword-research\",\n  \"version\": \"1.0.18\",\n  \"publishedAt\": 1789638761479\n}\n\nFile v1.0.18:reference/endpoints.md\n\n# serp-keyword-research — endpoint reference\n\n> Generated from `scripts/tools.json` by `scripts/generate.mjs` — do not edit by hand.\n\nEndpoints this skill uses, grouped by platform. Call them via `scripts/crawlora.sh` (see SKILL.md).\n\nAll paths are relative to the API base `https://api.crawlora.net/api/v1` and require the header `x-api-key: $CRAWLORA_API_KEY`. Path params like `{id}` are substituted into the URL; `GET` params go in the query string; `POST` params go in a JSON body.\n\n**36 endpoints across 5 platform group(s).**\n\n## Google (15)\n\n### `google_news`\n\n- **HTTP:** `GET /google/news`\n- **What:** Search Google News. Returns normalized Google News vertical results (title, source, link, age) parsed from the public Google News results page. Locale defaults to country=us and lang=en. Returns 503 when Google serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Google UI language; defaults to en; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n### `google_search`\n\n- **HTTP:** `POST /google/search`\n- **What:** Google search API. Returns normalized Google web search results. Results are fetched through proxied browser renderers that race several concurrent renders per request and return the first clean result, with stale-cache fallback when available. The endpoint returns 503 when Google serves a challenge page or unusable HTML. Rate limit is enforced at 1 request per second, and if the limit is exceeded a 429 status code is returned with rate limit headers.\n- **Params:** `searchOption` (object, **required**) — Search options\n- **REST body:** Send the value of the MCP argument `searchOption` directly as the JSON body; do not wrap it in a `searchOption` property.\n\n### `google_suggest`\n\n- **HTTP:** `GET /google/suggest`\n- **What:** Suggest Google search queries. Returns Google autosuggest query completions from the public unauthenticated suggest JSON endpoint.\n- **Params:** `count` (integer, optional) — Suggestions to return; defaults to 10, clamped to 1..12; `country` (string, optional) — Google result country; defaults to us; `lang` (string, optional) — Google UI language; defaults to en; `q` (string, **required**) — Search query prefix\n\n### `google_trends_categories`\n\n- **HTTP:** `GET /google/trends/categories`\n- **What:** Google Trends categories. Returns supported top-level Google Trends category ids and labels for Trending Now category filters.\n- **Params:** _none_\n\n### `google_trends_enums`\n\n- **HTTP:** `GET /google/trends/enums`\n- **What:** Google Trends enum metadata. Returns supported Google Trends enum values for explore/trending filters, including locations, date ranges, search types, categories, statuses, and sort modes.\n- **Params:** _none_\n\n### `google_trends_explore`\n\n- **HTTP:** `POST /google/trends/explore`\n- **What:** Google Trends explore data. Returns normalized Google Trends keyword analytics from internal Trends widget requests: interest over time, interest by region, related queries, and related topics when available.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_explore_interest_by_region`\n\n- **HTTP:** `POST /google/trends/explore/interest-by-region`\n- **What:** Google Trends interest by region. Returns only the interest-by-region widget from the Google Trends Explore widget flow. Supports multiple comparison terms and returns an empty interest_by_region array when Google returns no rows.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_explore_interest_over_time`\n\n- **HTTP:** `POST /google/trends/explore/interest-over-time`\n- **What:** Google Trends interest over time. Returns only the interest-over-time timeline from the Google Trends Explore widget flow. Supports multiple comparison terms.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_explore_related_topics`\n\n- **HTTP:** `POST /google/trends/explore/related-topics`\n- **What:** Google Trends related topics. Returns only the related topics widget from the Google Trends Explore widget flow. Returns an empty related_topics array when Google returns no topic rows for the requested term/filter combination.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_explore_rising_queries`\n\n- **HTTP:** `POST /google/trends/explore/rising-queries`\n- **What:** Google Trends explore rising queries. Returns the Rising related queries widget for one or more Google Trends explore terms. Returns an empty queries array when Google returns no rows for the requested term/filter combination.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_explore_top_queries`\n\n- **HTTP:** `POST /google/trends/explore/top-queries`\n- **What:** Google Trends explore top queries. Returns the Top related queries widget for one or more Google Trends explore terms. Returns an empty queries array when Google returns no rows for the requested term/filter combination.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_locations`\n\n- **HTTP:** `GET /google/trends/locations`\n- **What:** Google Trends locations. Returns supported Google Trends location codes. Explore endpoints also accept WORLDWIDE.\n- **Params:** _none_\n\n### `google_trends_trending`\n\n- **HTTP:** `GET /google/trends/trending`\n- **What:** Google Trends trending now data. Returns normalized Google Trends Trending Now rows from the internal TrendsUi batch RPC replay.\n- **Params:** `category` (integer, optional) — Trending category id; `geo` (string, optional) — Country/territory location code; `hl` (string, optional) — Google Trends UI locale; `limit` (integer, optional) — Maximum rows to return; `sort_by` (string, optional) — Sort mode; `status` (string, optional) — Trend status filter; `time_range` (string, optional) — Alias for window; `tz` (integer, optional) — Timezone offset minutes; `window` (string, optional) — Trend window\n\n### `google_trends_trending_detail`\n\n- **HTTP:** `POST /google/trends/trending/detail`\n- **What:** Google Trends trending term detail. Returns the Explore detail widgets for a single trending term, including interest over time, regional interest, top/rising related queries, and related topics when Google returns them.\n- **Params:** `request` (object, **required**) — Trending detail request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_videos`\n\n- **HTTP:** `GET /google/videos`\n- **What:** Search Google video results. Returns normalized Google video vertical results (title, platform, link, duration, age) parsed from the public Google video results page. Locale defaults to country=us and lang=en. Returns 503 when Google serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Google UI language; defaults to en; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n## Bing (5)\n\n### `bing_images`\n\n- **HTTP:** `GET /bing/images`\n- **What:** Search Bing image results. Returns normalized Bing image search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Bing image HTML/async pages and return 503 when Bing serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Bing UI language; defaults to en-us; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n### `bing_news`\n\n- **HTTP:** `GET /bing/news`\n- **What:** Search Bing news results. Returns normalized Bing news search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Bing news HTML/async pages and return 503 when Bing serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Bing UI language; defaults to en-us; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n### `bing_search`\n\n- **HTTP:** `GET /bing/search`\n- **What:** Search Bing web results. Returns normalized Bing web search results for a query string, including organic results, optional context panel data, related queries, people-also-ask questions, news modules, video modules, and page-based pagination. Empty optional blocks are omitted from the JSON response. Locale defaults to country=us and lang=en-us. Results are fetched with a Chrome-impersonated request client and return 503 on a genuine transport failure or challenge page. Bing occasionally serves a well-formed page whose results share no significant term with the query; when every hedged attempt hits this, the response is still returned as 200 with data.low_confidence set to true (and the X-Low-Confidence header) instead of being withheld, so callers get Bing's real answer plus an honest signal to double-check it rather than nothing. Queries that use the site: operator (for example site:gov.hu) are not supported: Bing serves a bot-verification challenge for them, so they are rejected with 400 before any request is made. Use the Google search endpoint (/api/v1/google/search) for domain-restricted searches.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Bing UI language; defaults to en-us; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n### `bing_suggest`\n\n- **HTTP:** `GET /bing/suggest`\n- **What:** Suggest Bing search queries. Returns Bing autosuggest query completions for a query prefix. Locale defaults to country=us and lang=en-us. Suggestions are fetched from public Bing suggest endpoints and trimmed to the requested count.\n- **Params:** `count` (integer, optional) — Suggestions to return; defaults to 10, clamped to 1..12; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Bing UI language; defaults to en-us; `q` (string, **required**) — Search query prefix\n\n### `bing_videos`\n\n- **HTTP:** `GET /bing/videos`\n- **What:** Search Bing video results. Returns normalized Bing video search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Bing video HTML/async pages and return 503 when Bing serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Bing UI language; defaults to en-us; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n## Brave (5)\n\n### `brave_images`\n\n- **HTTP:** `GET /brave/images`\n- **What:** Search Brave image results. Returns normalized Brave image search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Brave Search image HTML and return 503 when Brave serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results to return; defaults to 10, clamped to 1..50; `country` (string, optional) — Brave result country; defaults to us; `lang` (string, optional) — Brave UI language; defaults to en-us; `offset` (integer, optional) — Zero-based Brave result page; defaults to 0; `q` (string, **required**) — Search query\n\n### `brave_news`\n\n- **HTTP:** `GET /brave/news`\n- **What:** Search Brave news results. Returns normalized Brave news search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Brave Search news HTML and return 503 when Brave serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results to return; defaults to 10, clamped to 1..50; `country` (string, optional) — Brave result country; defaults to us; `date_from` (string, optional) — Custom start date in YYYY-MM-DD; requires date_to; `date_to` (string, optional) — Custom end date in YYYY-MM-DD; requires date_from; `lang` (string, optional) — Brave UI language; defaults to en-us; `offset` (integer, optional) — Zero-based Brave result page; defaults to 0; `q` (string, **required**) — Search query; `time_range` (string, optional) — Preset time filter: any, day, week, month, year, or custom\n\n### `brave_search`\n\n- **HTTP:** `GET /brave/search`\n- **What:** Search Brave. Returns normalized web search results from Brave Search for a query string, along with offset-based pagination, related queries, discussions, videos, and the right-side knowledge card when Brave includes one. Use time_range for preset ranges or date_from/date_to for a custom YYYY-MM-DD range. Locale defaults to country=us and lang=en-us.\n- **Params:** `country` (string, optional) — Brave result country; defaults to us; `date_from` (string, optional) — Custom start date in YYYY-MM-DD; requires date_to; `date_to` (string, optional) — Custom end date in YYYY-MM-DD; requires date_from; `lang` (string, optional) — Brave UI language; defaults to en-us; `offset` (integer, optional) — Zero-based Brave result page; `q` (string, **required**) — Search query; `time_range` (string, optional) — Preset time filter: any, day, week, month, year, or custom\n\n### `brave_suggest`\n\n- **HTTP:** `GET /brave/suggest`\n- **What:** Suggest Brave search queries. Returns Brave autosuggest query completions for a query prefix. Locale defaults to country=us and lang=en-us. Suggestions are fetched from public Brave Search suggest JSON and trimmed to the requested count.\n- **Params:** `count` (integer, optional) — Suggestions to return; defaults to 10, clamped to 1..12; `country` (string, optional) — Brave result country; defaults to us; `lang` (string, optional) — Brave UI language; defaults to en-us; `q` (string, **required**) — Search query prefix\n\n### `brave_videos`\n\n- **HTTP:** `GET /brave/videos`\n- **What:** Search Brave video results. Returns normalized Brave video search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Brave Search video HTML and return 503 when Brave serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results to return; defaults to 10, clamped to 1..50; `country` (string, optional) — Brave result country; defaults to us; `date_from` (string, optional) — Custom start date in YYYY-MM-DD; requires date_to; `date_to` (string, optional) — Custom end date in YYYY-MM-DD; requires date_from; `lang` (string, optional) — Brave UI language; defaults to en-us; `offset` (integer, optional) — Zero-based Brave result page; defaults to 0; `q` (string, **required**) — Search query; `time_range` (string, optional) — Preset time filter: any, day, week, month, year, or custom\n\n## DuckDuckGo Search (5)\n\n### `duckduckgo_image`\n\n- **HTTP:** `GET /duckduckgo/image`\n- **What:** Search DuckDuckGo image results. Returns normalized DuckDuckGo image results for a query string: title, source page URL, image URL, thumbnail, dimensions, and hostname, plus page-based pagination. Results are fetched from DuckDuckGo's own image JSON API.\n- **Params:** `page` (integer, optional) — 1-based page number, defaults to 1; `q` (string, **required**) — Search query; `region` (string, optional) — DuckDuckGo region/locale code, e.g. us-en, uk-en, wt-wt (worldwide, the default)\n\n### `duckduckgo_news`\n\n- **HTTP:** `GET /duckduckgo/news`\n- **What:** Search DuckDuckGo news results. Returns normalized DuckDuckGo news results for a query string: title, destination URL, source, excerpt, thumbnail, and relative/published time, plus page-based pagination. Results are fetched from DuckDuckGo's own news JSON API.\n- **Params:** `page` (integer, optional) — 1-based page number, defaults to 1; `q` (string, **required**) — Search query; `region` (string, optional) — DuckDuckGo region/locale code, e.g. us-en, uk-en, wt-wt (worldwide, the default)\n\n### `duckduckgo_search`\n\n- **HTTP:** `GET /duckduckgo/search`\n- **What:** Search DuckDuckGo web results. Returns normalized DuckDuckGo web search results for a query string: title, destination URL, description, and hostname, plus page-based pagination. DuckDuckGo wraps every result link in its own click-tracking redirect; this endpoint always returns the decoded destination URL, never the raw redirect link. Results are fetched from DuckDuckGo's own server-rendered search page.\n- **Params:** `page` (integer, optional) — 1-based page number, defaults to 1; `q` (string, **required**) — Search query; `region` (string, optional) — DuckDuckGo region/locale code, e.g. us-en, uk-en, wt-wt (worldwide, the default); `safe_search` (string, optional) — Safe search level, defaults to DuckDuckGo's own moderate setting when omitted; `time_range` (string, optional) — Restrict results to a recency window\n\n### `duckduckgo_shopping`\n\n- **HTTP:** `GET /duckduckgo/shopping`\n- **What:** Search DuckDuckGo shopping results. Returns normalized DuckDuckGo shopping results for a query string: title, brand, merchant, description, price, rating, and review count, plus total page count. DuckDuckGo's shopping vertical is ad-funded, syndicated product listings, not organic content; every product link is wrapped in an ad-click-tracking redirect with no clean destination to unwrap, so no destination URL is returned. DuckDuckGo's own pagination token for this vertical is an opaque per-response blob rather than a plain page offset, so only the first page is supported.\n- **Params:** `q` (string, **required**) — Search query; `region` (string, optional) — DuckDuckGo market code, e.g. us-en, uk-en\n\n### `duckduckgo_video`\n\n- **HTTP:** `GET /duckduckgo/video`\n- **What:** Search DuckDuckGo video results. Returns normalized DuckDuckGo video results for a query string: title, destination URL, description, duration, thumbnail, publisher/uploader, published time, and view count, plus page-based pagination. Results are fetched from DuckDuckGo's own video JSON API.\n- **Params:** `page` (integer, optional) — 1-based page number, defaults to 1; `q` (string, **required**) — Search query; `region` (string, optional) — DuckDuckGo region/locale code, e.g. us-en, uk-en, wt-wt (worldwide, the default)\n\n## Yahoo Search (6)\n\n### `yahoo_search`\n\n- **HTTP:** `GET /yahoo-search/search`\n- **What:** Search Yahoo web results. Returns normalized Yahoo web search results for a query string: title, destination URL, description, and hostname, plus page-based pagination. Yahoo wraps every result link in its own click-tracking redirect; this endpoint always returns the decoded destination URL, never the raw redirect link. Results are fetched from Yahoo's own server-rendered search page.\n- **Params:** `page` (integer, optional) — 1-based page number, defaults to 1; `q` (string, **required**) — Search query; `time_range` (string, optional) — Restrict results by recency. Omit for unfiltered ('Anytime').\n\n### `yahoo_search_images`\n\n- **HTTP:** `GET /yahoo-search/images`\n- **What:** Search Yahoo image results. Returns Yahoo's image-search results for a query: title, direct image URL, the page hosting the image, source domain, thumbnail, and original image dimensions when available. Results are fetched from Yahoo's own server-rendered image-search page.\n- **Params:** `q` (string, **required**) — Search query\n\n### `yahoo_search_local`\n\n- **HTTP:** `GET /yahoo-search/local`\n- **What:** Search Yahoo local business results. Returns Yahoo's local-business-search results for a query: name, category, price range, address, phone, open status, rating, and review count. Location is resolved from the query text itself, the same way a user would type into Yahoo's own local search box (e.g. \"pizza near seattle wa\"), not a separate coordinate parameter. Results are fetched from Yahoo's own server-rendered local-search page.\n- **Params:** `q` (string, **required**) — Search query, including any location intent\n\n### `yahoo_search_news`\n\n- **HTTP:** `GET /yahoo-search/news`\n- **What:** Search Yahoo news results. Returns Yahoo's news-search results for a query: title, destination URL, description, source, and relative publish age. Results are fetched from Yahoo's own server-rendered news-search page (news.search.yahoo.com) -- a distinct product from the yahoo-news family, which covers the www.yahoo.com/news portal itself. Yahoo wraps every result link in its own click-tracking redirect; this endpoint always returns the decoded destination URL, never the raw redirect link.\n- **Params:** `q` (string, **required**) — Search query\n\n### `yahoo_search_suggest`\n\n- **HTTP:** `GET /yahoo-search/suggest`\n- **What:** Yahoo web search autocomplete suggestions. Returns Yahoo's own search-box autocomplete suggestions for a partial query: a flat list of suggested search terms, each optionally carrying knowledge-panel entity metadata (type, image, subtitle, description) when Yahoo resolves the term to a known company, place, product, or similar entity rather than a plain phrase.\n- **Params:** `count` (integer, optional) — Number of suggestions to return, default 10, clamped to 1..20; `q` (string, **required**) — Partial search query to autocomplete\n\n### `yahoo_search_videos`\n\n- **HTTP:** `GET /yahoo-search/videos`\n- **What:** Search Yahoo video results. Returns Yahoo's video-search results for a query: title, destination page URL, source domain, description, thumbnail, and duration. Results are fetched from Yahoo's own server-rendered video-search page.\n- **Params:** `q` (string, **required**) — Search query\n\nFile v1.0.18:skill-card.md\n\n## Description:\n\nRuns SERP and keyword research via the Crawlora API, covering Google, Bing, Brave, DuckDuckGo, Yahoo, and Google Trends, and returns normalized JSON for rankings, SERP snapshots, keyword suggestions, and trend data.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[crawlora-org](https://clawhub.ai/user/crawlora-org)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users, developers, and SEO researchers use this skill to query Crawlora for public search-engine rankings, SERP snapshots, autocomplete ideas, and Google Trends signals without scraping result pages directly.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Search keywords, trend terms, locale parameters, and similar request data are sent to Crawlora using the user's API key.\n\nMitigation: Use only approved public research terms, and avoid secrets, credentials, confidential investigation terms, or regulated personal data unless that third-party use is approved.\n\nRisk: A Crawlora API key could be exposed if users hardcode it, commit it, or pass it through unsupported request patterns.\n\nMitigation: Keep the key in the CRAWLORA_API_KEY environment variable and use the provided helper, which keeps the key out of command-line arguments, restricts routes, and uses a private temporary curl config.\n\n## Reference(s):\n\n- [Endpoint Reference](reference/endpoints.md)\n- [Crawlora Website](https://crawlora.net)\n- [Crawlora API Base](https://api.crawlora.net/api/v1)\n- [ClawHub Skill Page](https://clawhub.ai/crawlora-org/skills/serp-keyword-research)\n- [Crawlora Publisher Profile](https://clawhub.ai/user/crawlora-org)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, code, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with shell commands and JSON API responses]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Outputs are generated through documented Crawlora API routes and may include normalized public search results, keyword suggestions, trend series, related topics, and related or rising queries.]\n\n## Skill Version(s):\n\n1.0.18 (source: server release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.0.17: 5 files, 10656 bytes\n\nFiles: reference/endpoints.md (23355b), scripts/crawlora.sh (7158b), skill-card.md (2058b), SKILL.md (4420b), _meta.json (141b)\n\nFile v1.0.17:SKILL.md\n\n---\nname: serp-keyword-research\ndescription: Runs SERP and keyword research via the Crawlora API — Google, Bing, Brave, DuckDuckGo, and Yahoo search results plus Google Trends interest-over-time and related/rising queries — returning clean JSON. Use when the user wants search-engine rankings, SERP snapshots, autocomplete/keyword suggestions, or trend data instead of scraping result pages.\n---\n\n# SERP & keyword research\n\nCapture search-engine results (Google, Bing, Brave, DuckDuckGo, Yahoo) and\nkeyword/trend signals (Google autosuggest, Google Trends) as normalized\nJSON from the Crawlora API.\n\n## When to use this skill\n\n- \"What ranks for <query> on Google / Bing?\" / \"snapshot the SERP for …\".\n- \"Keyword ideas / autocomplete for …\" (suggest endpoints).\n- \"Is <topic> trending?\" / \"interest over time / by region for <keyword>.\"\n- \"Related and rising queries for …\" (Google Trends).\n- SEO/SERP monitoring, keyword discovery, or trend research.\n\n## Setup (one-time)\n\n- Get a free Crawlora API key (2,000 credits/mo, no card) at [https://crawlora.net](https://crawlora.net?utm_source=github&utm_medium=referral&utm_campaign=crawlora-skills).\n- Set `CRAWLORA_API_KEY` in the environment before running the helper.\n- The helper reads `CRAWLORA_API_KEY` from the environment and sends requests to `https://api.crawlora.net/api/v1`. Missing/invalid key → `401`.\n\n## How it works\n\n1. **SERP** — Google search is `POST /google/search` with flat `keyword`, `language`, and `country` fields;\n   Bing, Brave, DuckDuckGo, and Yahoo are plain `GET` with `q`:\n   `/bing/search`, `/brave/search`, `/duckduckgo/search`, `/yahoo-search/search`.\n   Cross-check engines for coverage; on a `503` challenge, fall back to another engine.\n2. **Verticals** — news/videos/images per engine (`/google/news`, `/bing/videos`,\n   `/duckduckgo/news`, `/duckduckgo/image`, `/duckduckgo/video`, `/duckduckgo/shopping`, …).\n3. **Keyword ideas** — autosuggest: `GET /google/suggest?q=...` (and `/bing/suggest`,\n   `/brave/suggest`).\n4. **Trends** — Google Trends `POST` endpoints:\n   `/google/trends/explore/interest-over-time`, `/interest-by-region`,\n   `/related-topics`, `/rising-queries`, `/top-queries` (body: `{\"keywords\":[...]}`),\n   plus `GET /google/trends/trending` for what's hot now.\n\nFull endpoint list, methods, and params: [`reference/endpoints.md`](reference/endpoints.md).\n\n## Calling the API\n\n```sh\n# GET search engines + suggest:\nscripts/crawlora.sh /bing/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /brave/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /duckduckgo/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /yahoo-search/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /google/suggest q=\"web scraping\" | jq '.'\n\n# POST endpoints take a JSON body (note -X POST):\nscripts/crawlora.sh -X POST /google/search '{\"keyword\":\"web scraping api\",\"language\":\"en\",\"country\":\"us\"}' | jq '.'\nscripts/crawlora.sh -X POST /google/trends/explore/interest-over-time '{\"keywords\":[\"web scraping\"]}' | jq '.'\n```\n\nUse `scripts/crawlora.sh` for all requests; it keeps the API key out of command-line arguments.\n\n\n## Endpoint reference\n\nSee [`reference/endpoints.md`](reference/endpoints.md) for every Google, Bing,\nBrave, DuckDuckGo, Yahoo, and Google Trends endpoint this skill uses (method,\npath, params, description).\n\n## Examples\n\n- **SERP snapshot:** `POST /google/search` (and `/bing/search`) for a target query;\n  record the ranked result titles/URLs to track positions over time.\n- **Keyword expansion:** seed term → `/google/suggest` → for each suggestion,\n  `POST /google/trends/explore/rising-queries` to find momentum.\n- **Trend check:** `POST /google/trends/explore/interest-over-time` with\n  `{\"keywords\":[\"electric bikes\",\"e-bikes\"]}` and compare the series.\n\n## Notes & limits\n\n- **Credits / pay-on-success:** billed only on `2xx`; free tier 2,000 credits/mo.\n  Key at [https://crawlora.net](https://crawlora.net?utm_source=github&utm_medium=referral&utm_campaign=crawlora-skills).\n- **Public data only** — public search results; respect each engine's terms.\n- **Security:** key lives in `CRAWLORA_API_KEY` only — never hardcode, query-param, or commit it.\n- Search endpoints may return `503` when the engine serves a challenge page —\n  retry or switch engines (Google ↔ Bing ↔ Brave). Google search is rate-limited\n  to ~1 req/s (`429` on excess).\n\nFile v1.0.17:_meta.json\n\n{\n  \"ownerId\": \"kn70shhkf6qpfwgfrbgtep2wkd8c6b4t\",\n  \"slug\": \"serp-keyword-research\",\n  \"version\": \"1.0.17\",\n  \"publishedAt\": 1789358344503\n}\n\nFile v1.0.17:reference/endpoints.md\n\n# serp-keyword-research — endpoint reference\n\n> Generated from `scripts/tools.json` by `scripts/generate.mjs` — do not edit by hand.\n\nEndpoints this skill uses, grouped by platform. Call them via `scripts/crawlora.sh` (see SKILL.md).\n\nAll paths are relative to the API base `https://api.crawlora.net/api/v1` and require the header `x-api-key: $CRAWLORA_API_KEY`. Path params like `{id}` are substituted into the URL; `GET` params go in the query string; `POST` params go in a JSON body.\n\n**36 endpoints across 5 platform group(s).**\n\n## Google (15)\n\n### `google_news`\n\n- **HTTP:** `GET /google/news`\n- **What:** Search Google News. Returns normalized Google News vertical results (title, source, link, age) parsed from the public Google News results page. Locale defaults to country=us and lang=en. Returns 503 when Google serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Google UI language; defaults to en; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n### `google_search`\n\n- **HTTP:** `POST /google/search`\n- **What:** Google search API. Returns normalized Google web search results. Results are fetched through proxied browser renderers that race several concurrent renders per request and return the first clean result, with stale-cache fallback when available. The endpoint returns 503 when Google serves a challenge page or unusable HTML. Rate limit is enforced at 1 request per second, and if the limit is exceeded a 429 status code is returned with rate limit headers.\n- **Params:** `searchOption` (object, **required**) — Search options\n- **REST body:** Send the value of the MCP argument `searchOption` directly as the JSON body; do not wrap it in a `searchOption` property.\n\n### `google_suggest`\n\n- **HTTP:** `GET /google/suggest`\n- **What:** Suggest Google search queries. Returns Google autosuggest query completions from the public unauthenticated suggest JSON endpoint.\n- **Params:** `count` (integer, optional) — Suggestions to return; defaults to 10, clamped to 1..12; `country` (string, optional) — Google result country; defaults to us; `lang` (string, optional) — Google UI language; defaults to en; `q` (string, **required**) — Search query prefix\n\n### `google_trends_categories`\n\n- **HTTP:** `GET /google/trends/categories`\n- **What:** Google Trends categories. Returns supported top-level Google Trends category ids and labels for Trending Now category filters.\n- **Params:** _none_\n\n### `google_trends_enums`\n\n- **HTTP:** `GET /google/trends/enums`\n- **What:** Google Trends enum metadata. Returns supported Google Trends enum values for explore/trending filters, including locations, date ranges, search types, categories, statuses, and sort modes.\n- **Params:** _none_\n\n### `google_trends_explore`\n\n- **HTTP:** `POST /google/trends/explore`\n- **What:** Google Trends explore data. Returns normalized Google Trends keyword analytics from internal Trends widget requests: interest over time, interest by region, related queries, and related topics when available.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_explore_interest_by_region`\n\n- **HTTP:** `POST /google/trends/explore/interest-by-region`\n- **What:** Google Trends interest by region. Returns only the interest-by-region widget from the Google Trends Explore widget flow. Supports multiple comparison terms and returns an empty interest_by_region array when Google returns no rows.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_explore_interest_over_time`\n\n- **HTTP:** `POST /google/trends/explore/interest-over-time`\n- **What:** Google Trends interest over time. Returns only the interest-over-time timeline from the Google Trends Explore widget flow. Supports multiple comparison terms.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_explore_related_topics`\n\n- **HTTP:** `POST /google/trends/explore/related-topics`\n- **What:** Google Trends related topics. Returns only the related topics widget from the Google Trends Explore widget flow. Returns an empty related_topics array when Google returns no topic rows for the requested term/filter combination.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_explore_rising_queries`\n\n- **HTTP:** `POST /google/trends/explore/rising-queries`\n- **What:** Google Trends explore rising queries. Returns the Rising related queries widget for one or more Google Trends explore terms. Returns an empty queries array when Google returns no rows for the requested term/filter combination.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_explore_top_queries`\n\n- **HTTP:** `POST /google/trends/explore/top-queries`\n- **What:** Google Trends explore top queries. Returns the Top related queries widget for one or more Google Trends explore terms. Returns an empty queries array when Google returns no rows for the requested term/filter combination.\n- **Params:** `request` (object, **required**) — Explore request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_trends_locations`\n\n- **HTTP:** `GET /google/trends/locations`\n- **What:** Google Trends locations. Returns supported Google Trends location codes. Explore endpoints also accept WORLDWIDE.\n- **Params:** _none_\n\n### `google_trends_trending`\n\n- **HTTP:** `GET /google/trends/trending`\n- **What:** Google Trends trending now data. Returns normalized Google Trends Trending Now rows from the internal TrendsUi batch RPC replay.\n- **Params:** `category` (integer, optional) — Trending category id; `geo` (string, optional) — Country/territory location code; `hl` (string, optional) — Google Trends UI locale; `limit` (integer, optional) — Maximum rows to return; `sort_by` (string, optional) — Sort mode; `status` (string, optional) — Trend status filter; `time_range` (string, optional) — Alias for window; `tz` (integer, optional) — Timezone offset minutes; `window` (string, optional) — Trend window\n\n### `google_trends_trending_detail`\n\n- **HTTP:** `POST /google/trends/trending/detail`\n- **What:** Google Trends trending term detail. Returns the Explore detail widgets for a single trending term, including interest over time, regional interest, top/rising related queries, and related topics when Google returns them.\n- **Params:** `request` (object, **required**) — Trending detail request\n- **REST body:** Send the value of the MCP argument `request` directly as the JSON body; do not wrap it in a `request` property.\n\n### `google_videos`\n\n- **HTTP:** `GET /google/videos`\n- **What:** Search Google video results. Returns normalized Google video vertical results (title, platform, link, duration, age) parsed from the public Google video results page. Locale defaults to country=us and lang=en. Returns 503 when Google serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Google UI language; defaults to en; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n## Bing (5)\n\n### `bing_images`\n\n- **HTTP:** `GET /bing/images`\n- **What:** Search Bing image results. Returns normalized Bing image search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Bing image HTML/async pages and return 503 when Bing serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Bing UI language; defaults to en-us; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n### `bing_news`\n\n- **HTTP:** `GET /bing/news`\n- **What:** Search Bing news results. Returns normalized Bing news search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Bing news HTML/async pages and return 503 when Bing serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Bing UI language; defaults to en-us; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n### `bing_search`\n\n- **HTTP:** `GET /bing/search`\n- **What:** Search Bing web results. Returns normalized Bing web search results for a query string, including organic results, optional context panel data, related queries, people-also-ask questions, news modules, video modules, and page-based pagination. Empty optional blocks are omitted from the JSON response. Locale defaults to country=us and lang=en-us. Results are fetched with a Chrome-impersonated request client and return 503 on a genuine transport failure or challenge page. Bing occasionally serves a well-formed page whose results share no significant term with the query; when every hedged attempt hits this, the response is still returned as 200 with data.low_confidence set to true (and the X-Low-Confidence header) instead of being withheld, so callers get Bing's real answer plus an honest signal to double-check it rather than nothing. Queries that use the site: operator (for example site:gov.hu) are not supported: Bing serves a bot-verification challenge for them, so they are rejected with 400 before any request is made. Use the Google search endpoint (/api/v1/google/search) for domain-restricted searches.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Bing UI language; defaults to en-us; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n### `bing_suggest`\n\n- **HTTP:** `GET /bing/suggest`\n- **What:** Suggest Bing search queries. Returns Bing autosuggest query completions for a query prefix. Locale defaults to country=us and lang=en-us. Suggestions are fetched from public Bing suggest endpoints and trimmed to the requested count.\n- **Params:** `count` (integer, optional) — Suggestions to return; defaults to 10, clamped to 1..12; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Bing UI language; defaults to en-us; `q` (string, **required**) — Search query prefix\n\n### `bing_videos`\n\n- **HTTP:** `GET /bing/videos`\n- **What:** Search Bing video results. Returns normalized Bing video search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Bing video HTML/async pages and return 503 when Bing serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Bing UI language; defaults to en-us; `page` (integer, optional) — 1-based page number; defaults to 1; `q` (string, **required**) — Search query\n\n## Brave (5)\n\n### `brave_images`\n\n- **HTTP:** `GET /brave/images`\n- **What:** Search Brave image results. Returns normalized Brave image search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Brave Search image HTML and return 503 when Brave serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results to return; defaults to 10, clamped to 1..50; `country` (string, optional) — Brave result country; defaults to us; `lang` (string, optional) — Brave UI language; defaults to en-us; `offset` (integer, optional) — Zero-based Brave result page; defaults to 0; `q` (string, **required**) — Search query\n\n### `brave_news`\n\n- **HTTP:** `GET /brave/news`\n- **What:** Search Brave news results. Returns normalized Brave news search results for a query string. Locale defaults to country=us and lang=en-us. Results are fetched from public Brave Search news HTML and return 503 when Brave serves a challenge page or unusable HTML.\n- **Params:** `count` (integer, optional) — Results to return; defaults to 10, clamped to 1..50; `country` (string, optional) — Brave result country; defaults to us; `date_from` (string, optional) — Custom start date in YYYY-MM-DD; requires date_to; `date_to` (string, optional) — Custom end date in YYYY-MM-DD; requires date_from; `lang` (string, optional) — Brave UI language; defaults to en-us; `offset` (integer, optional) — Zero-based Brave result page; defaults to 0; `q` (string, **required**) — Search query; `time_range` (string, optional) — Preset time filter: any, day, week, month, year, or custom\n\n### `brave_search`\n\n- **HTTP:** `GET /brave/search`\n- **What:** Search Brave. Returns normalized web search results from Brave Search for a query string, along with offset-based pagination, related queries, discussions, videos, and the right-side knowledge card when Brave includes one. Use time_range for preset ranges or date_from/date_to for a custom YYYY-MM-DD range. Local\n\nArchive v1.0.16: 5 files, 12343 bytes\n\nFiles: reference/endpoints.md (31671b), scripts/crawlora.sh (7001b), skill-card.md (2520b), SKILL.md (4420b), _meta.json (141b)\n\nArchive v1.0.15: 5 files, 11965 bytes\n\nFiles: reference/endpoints.md (31671b), scripts/crawlora.sh (5561b), skill-card.md (2294b), SKILL.md (4420b), _meta.json (141b)\n\nArchive v1.0.14: 5 files, 11918 bytes\n\nFiles: reference/endpoints.md (31671b), scripts/crawlora.sh (5304b), skill-card.md (2370b), SKILL.md (4420b), _meta.json (141b)\n\nArchive v1.0.13: 5 files, 11745 bytes\n\nFiles: reference/endpoints.md (31671b), scripts/crawlora.sh (4979b), skill-card.md (2365b), SKILL.md (4457b), _meta.json (141b)\n\nArchive v1.0.12: 5 files, 11574 bytes\n\nFiles: reference/endpoints.md (31671b), scripts/crawlora.sh (4679b), skill-card.md (2334b), SKILL.md (4457b), _meta.json (141b)","readmeExcerpt":"Skill: serp-keyword-research Owner: crawlora-org Summary: Runs SERP and keyword research via the Crawlora API — Google, Bing, Brave, DuckDuckGo, and Yahoo search results plus Google Trends interest-over-time and related/rising queries — returning clean JSON. Use when the user wants search-engine rankings, SERP snapshots, autocomplete/keyword suggestions, or trend data instead of scraping result pages. Tags: latest:1.","codeSnippets":[],"executableExamples":[{"language":"sh","snippet":"# GET search engines + suggest:\nscripts/crawlora.sh /bing/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /brave/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /duckduckgo/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /yahoo-search/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /google/suggest q=\"web scraping\" | jq '.'\n\n# POST endpoints take a JSON body (note -X POST):\nscripts/crawlora.sh -X POST /google/search '{\"keyword\":\"web scraping api\",\"language\":\"en\",\"country\":\"us\"}' | jq '.'\nscripts/crawlora.sh -X POST /google/trends/explore/interest-over-time '{\"keywords\":[\"web scraping\"]}' | jq '.'"},{"language":"sh","snippet":"# GET search engines + suggest:\nscripts/crawlora.sh /bing/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /brave/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /duckduckgo/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /yahoo-search/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /google/suggest q=\"web scraping\" | jq '.'\n\n# POST endpoints take a JSON body (note -X POST):\nscripts/crawlora.sh -X POST /google/search '{\"keyword\":\"web scraping api\",\"language\":\"en\",\"country\":\"us\"}' | jq '.'\nscripts/crawlora.sh -X POST /google/trends/explore/interest-over-time '{\"keywords\":[\"web scraping\"]}' | jq '.'"},{"language":"sh","snippet":"# GET search engines + suggest:\nscripts/crawlora.sh /bing/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /brave/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /duckduckgo/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /yahoo-search/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /google/suggest q=\"web scraping\" | jq '.'\n\n# POST endpoints take a JSON body (note -X POST):\nscripts/crawlora.sh -X POST /google/search '{\"keyword\":\"web scraping api\",\"language\":\"en\",\"country\":\"us\"}' | jq '.'\nscripts/crawlora.sh -X POST /google/trends/explore/interest-over-time '{\"keywords\":[\"web scraping\"]}' | jq '.'"},{"language":"sh","snippet":"# GET search engines + suggest:\nscripts/crawlora.sh /bing/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /brave/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /duckduckgo/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /yahoo-search/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /google/suggest q=\"web scraping\" | jq '.'\n\n# POST endpoints take a JSON body (note -X POST):\nscripts/crawlora.sh -X POST /google/search '{\"keyword\":\"web scraping api\",\"language\":\"en\",\"country\":\"us\"}' | jq '.'\nscripts/crawlora.sh -X POST /google/trends/explore/interest-over-time '{\"keywords\":[\"web scraping\"]}' | jq '.'"},{"language":"sh","snippet":"# GET search engines + suggest:\nscripts/crawlora.sh /bing/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /brave/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /duckduckgo/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /yahoo-search/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /google/suggest q=\"web scraping\" | jq '.'\n\n# POST endpoints take a JSON body (note -X POST):\nscripts/crawlora.sh -X POST /google/search '{\"keyword\":\"web scraping api\",\"language\":\"en\",\"country\":\"us\"}' | jq '.'\nscripts/crawlora.sh -X POST /google/trends/explore/interest-over-time '{\"keywords\":[\"web scraping\"]}' | jq '.'"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: serp-keyword-research\ndescription: Runs SERP and keyword research via the Crawlora API — Google, Bing, Brave, DuckDuckGo, and Yahoo search results plus Google Trends interest-over-time and related/rising queries — returning clean JSON. Use when the user wants search-engine rankings, SERP snapshots, autocomplete/keyword suggestions, or trend data instead of scraping result pages.\n---\n\n# SERP & keyword research\n\nCapture search-engine results (Google, Bing, Brave, DuckDuckGo, Yahoo) and\nkeyword/trend signals (Google autosuggest, Google Trends) as normalized\nJSON from the Crawlora API.\n\n## When to use this skill\n\n- \"What ranks for <query> on Google / Bing?\" / \"snapshot the SERP for …\".\n- \"Keyword ideas / autocomplete for …\" (suggest endpoints).\n- \"Is <topic> trending?\" / \"interest over time / by region for <keyword>.\"\n- \"Related and rising queries for …\" (Google Trends).\n- SEO/SERP monitoring, keyword discovery, or trend research.\n\n## Setup (one-time)\n\n- Get a free Crawlora API key (2,000 credits/mo, no card) at [https://crawlora.net](https://crawlora.net?utm_source=github&utm_medium=referral&utm_campaign=crawlora-skills).\n- Set `CRAWLORA_API_KEY` in the environment before running the helper.\n- The helper reads `CRAWLORA_API_KEY` from the environment and sends requests to `https://api.crawlora.net/api/v1`. Missing/invalid key → `401`.\n\n## How it works\n\n1. **SERP** — Google search is `POST /google/search` with flat `keyword`, `language`, and `country` fields;\n   Bing, Brave, DuckDuckGo, and Yahoo are plain `GET` with `q`:\n   `/bing/search`, `/brave/search`, `/duckduckgo/search`, `/yahoo-search/search`.\n   Cross-check engines for coverage; on a `503` challenge, fall back to another engine.\n2. **Verticals** — news/videos/images per engine (`/google/news`, `/bing/videos`,\n   `/duckduckgo/news`, `/duckduckgo/image`, `/duckduckgo/video`, `/duckduckgo/shopping`, …).\n3. **Keyword ideas** — autosuggest: `GET /google/suggest?q=...` (and `/bing/suggest`,\n   `/brave/suggest`).\n4. **Trends** — Google Trends `POST` endpoints:\n   `/google/trends/explore/interest-over-time`, `/interest-by-region`,\n   `/related-topics`, `/rising-queries`, `/top-queries` (body: `{\"keywords\":[...]}`),\n   plus `GET /google/trends/trending` for what's hot now.\n\nFull endpoint list, methods, and params: [`reference/endpoints.md`](reference/endpoints.md).\n\n## Calling the API\n\n```sh\n# GET search engines + suggest:\nscripts/crawlora.sh /bing/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /brave/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /duckduckgo/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /yahoo-search/search q=\"web scraping api\" | jq '.'\nscripts/crawlora.sh /google/suggest q=\"web scraping\" | jq '.'\n\n# POST endpoints take a JSON body (note -X POST):\nscripts/crawlora.sh -X POST /google/search '{\"keyword\":\"web scraping api\",\"language\":\"en\",\"country\":\"us\"}' | jq '.'\nscripts/crawlora.sh -X POST /google/trends/explore/interest-over-time '{\"keywords\""},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn70shhkf6qpfwgfrbgtep2wkd8c6b4t\",\n  \"slug\": \"serp-keyword-research\",\n  \"version\": \"1.0.21\",\n  \"publishedAt\": 1791251970777\n}"},{"path":"reference/endpoints.md","content":"# serp-keyword-research — endpoint reference\n\n> Generated from `scripts/tools.json` by `scripts/generate.mjs` — do not edit by hand.\n\nEndpoints this skill uses, grouped by platform. Call them via `scripts/crawlora.sh` (see SKILL.md).\n\nAll paths are relative to the API base `https://api.crawlora.net/api/v1` and require the header `x-api-key: $CRAWLORA_API_KEY`. Path params like `{id}` are substituted into the URL; `GET` params go in the query string; `POST` params go in a JSON body.\n\n**37 endpoints across 5 platform group(s).**\n\n## Google (15)\n\n### `google_news`\n\n- **HTTP:** `GET /google/news`\n- **What:** Search Google News. Returns current Google News search results using anonymous HTTP requests with fresh proxy profiles, without browser rendering. Pages slice the finite result snapshot; they do not traverse the Google Search index. Results include title, source, publisher article URL, age, and thumbnail when available. Valid no-results searches and exhausted pages return an empty array. Locale defaults to country=us and lang=en. Returns 503 for blocked or malformed upstream responses.\n- **Params:** `count` (integer, optional) — Results per page; defaults to 10, clamped to 1..50; `country` (string, optional) — Two-letter country code; defaults to us; `lang` (string, optional) — Google UI language; defaults to en; `page` (integer, optional) — 1-based page within the current finite result snapshot; defaults to 1; `q` (string, **required**) — Search query\n\n### `google_news_search`\n\n- **HTTP:** `POST /google/news`\n- **What:** Search Google News with JSON. Restored JSON compatibility endpoint. Returns current Google News articles using anonymous HTTP requests with fresh proxy profiles, without browser rendering. Pages slice the finite current result snapshot. Uses the legacy result array and field names; no-results searches and exhausted pages return an empty result array.\n- **Params:** `searchOption` (object, **required**) — Search options; keyword, language and country are required. limit defaults to 10 and is clamped to 10..100; page defaults to 1.\n- **REST body:** Send the value of the MCP argument `searchOption` directly as the JSON body; do not wrap it in a `searchOption` property.\n\n### `google_suggest`\n\n- **HTTP:** `GET /google/suggest`\n- **What:** Suggest Google search queries. Returns Google autosuggest query completions from the public unauthenticated suggest JSON endpoint. `source` selects the web, YouTube, or shopping suggestion list, and `rich=true` adds a type, relevance score, and short description to each suggestion.\n- **Params:** `count` (integer, optional) — Suggestions to return; defaults to 10, clamped to 1..12; `country` (string, optional) — Google result country; defaults to us; `lang` (string, optional) — Google UI language; defaults to en; `q` (string, **required**) — Search query prefix; `rich` (boolean, optional) — Add Google's type, relevance score, and description to each suggestion; defaults to false; `source` (string, opt"},{"path":"skill-card.md","content":"## Description:\n\nRuns search-engine results, keyword suggestions, and Google Trends research through the Crawlora API, returning structured JSON.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[crawlora-org](https://clawhub.ai/user/crawlora-org)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nSEO practitioners, marketers, and developers use this skill to compare public search rankings, discover related keywords, and examine search trends across engines and regions.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Search terms and trend keywords are sent to Crawlora and related search providers.\n\nMitigation: Use only public, non-sensitive queries; do not submit secrets, private identifiers, or regulated data.\n\nRisk: An exposed Crawlora API key could allow unauthorized use.\n\nMitigation: Keep CRAWLORA_API_KEY in the environment; never hardcode or commit it.\n\n## Reference(s):\n\n- [Endpoint reference](reference/endpoints.md)\n- [ClawHub skill release](https://clawhub.ai/crawlora-org/skills/serp-keyword-research)\n\n## Skill Output:\n\n**Output Type(s):** [Text, JSON, Guidance]\n\n**Output Format:** [Plain text or Markdown summaries with structured JSON results]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Results reflect public search and trends data; coverage and availability vary by engine.]\n\n## Skill Version(s):\n\n1.0.21 (source: ClawHub release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment."}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":1542,"uniquenessScore":41,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-11T08:43:13.771Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-11T08:43:13.771Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-11T10:51:52.339Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}