Fetch real-time web data via the hasdata CLI. Use when the user wants search results, news, fact-checks, product or seller info, current prices, reviews, rea...
---
name: hasdata
description: Fetch real-time web data via the hasdata CLI. Use when the user wants search results, news, fact-checks, product or seller info, current prices, reviews, real-estate listings or sold comps, vacation rentals, local-business contact details, job postings, salary research, search trends, images, flights, social profiles, or to scrape any URL (HTML / markdown / AI-extracted JSON). Also use when the user asks to summarize a web page, ground a prompt with current information, verify a URL is live or render a JavaScript-heavy page, monitor a price over time, find a phone number or address for a business, build a competitor map, identify recent sold comparables, gather employer reviews, fan out a list of items to per-item details, or check what's being said online about a topic right now. Backed by Google, Bing, Amazon, Shopify, Zillow, Redfin, Airbnb, Yelp, YellowPages, Indeed, Glassdoor, Instagram, Google Maps / Trends / News / Images / Flights / Events APIs.
homepage: https://github.com/HasData/hasdata-cli
metadata:
clawdbot:
emoji: "🔎"
primaryEnv: HASDATA_API_KEY
requires:
bins: [hasdata]
---
# hasdata
Use the `hasdata` CLI for real-time web data. One subcommand per API — flags, enums, defaults are derived from the live schema at `api.hasdata.com/apis`.
## Prerequisites
- `command -v hasdata` — if missing, install with `curl -sSL https://raw.githubusercontent.com/HasData/hasdata-cli/main/install.sh | sh`.
- One-time setup: the user runs `hasdata configure`, pastes their API key, and it's saved to `~/.hasdata/config.yaml` (mode 0600). Every future call picks it up automatically.
- If a call fails with `no API key configured`, the user hasn't run `hasdata configure` yet — tell them to. **Never invent a key.**
## Quick start
```bash
hasdata <api> --flag value [--flag value ...] --raw | jq .
```
Always pass `--raw` when piping to `jq` (skips pretty-print and TTY detection). Use `--pretty` only for human-readable terminal output.
## Picking the right subcommand
| User intent | Subcommand |
| --- | --- |
| Web search ("what does Google say about…") | `google-serp` (full features) or `google-serp-light` (cheap, single page) |
| Latest news | `google-news` |
| AI Mode SERP | `google-ai-mode` |
| Shopping / product prices | `google-shopping` (broad), `amazon-search` / `amazon-product` (Amazon), `shopify-products` (Shopify) |
| Immersive product page | `google-immersive-product` |
| Maps / places / reviews | `google-maps`, `google-maps-place`, `google-maps-reviews`, `google-maps-photos` |
| Yelp / YellowPages local data | `yelp-search`, `yelp-place`, `yellowpages-search`, `yellowpages-place` |
| Real-estate listings | `zillow-listing`, `redfin-listing`, `airbnb-listing` |
| Real-estate single property deep dive | `zillow-property`, `redfin-property`, `airbnb-property` |
| Jobs | `indeed-listing`, `indeed-job`, `glassdoor-listing`, `glassdoor-job` |
| Bing search | `bing-serp` |
| Trends | `google-trends` |
| Images | `google-images` |
| Flights | `google-flights` |
| Short videos | `google-short-videos` |
| Events | `google-events` |
| Instagram profile | `instagram-profile` |
| Amazon seller | `amazon-seller`, `amazon-seller-products` |
| **Scrape a specific URL** | `web-scraping` — supports JS rendering, proxies, markdown output, AI extraction, screenshots |
For exact flags of a subcommand, run `hasdata <api> --help` or read the matching file in `references/`.
## Non-obvious triggers (when to reach for hasdata even if the user doesn't say "scrape")
The user often won't ask for a SERP API or a scraper directly. Map these intents to the skill:
- **"Is this still true?" / "What's the latest on X?" / "Has Y happened yet?"** — LLM training data is stale. Run `google-serp` or `google-news` to ground the answer.
- **"Summarize this article" / "TL;DR this URL"** — Use `web-scraping --output-format markdown` and feed the markdown into the summary prompt. Beats copy-paste because it strips ads, nav, scripts.
- **"Verify this link" / "Is this site real?"** — `web-scraping --url X --no-block-resources` returns status + screenshot. Or `google-serp --q "site:example.com"`.
- **"What does X say about itself?"** — Pull the company's own homepage with `web-scraping --output-format markdown`, then summarize.
- **"Find me alternatives to X"** — `google-serp --q "X alternatives"` or `google-shopping --q "X competitors"`.
- **"What's the going rate for X?"** — `google-shopping` (broad) or `amazon-search` (Amazon-specific) with `jq` to extract the price distribution.
- **"Phone number / address for X"** — `google-maps-place` or `yelp-place`. Don't guess from training data.
- **"Are people happy with X service?" / "Is X reputable?"** — `google-maps-reviews --place-id ... --sort lowest` for negative samples; `glassdoor-job` for employer rep.
- **"What's the salary range for Y role?"** — `indeed-listing` filtered by role + location, then `jq` over `.jobs[].salary`.
- **"Find me homes/apartments matching X criteria"** — `zillow-listing` / `redfin-listing` / `airbnb-listing` with the corresponding filters.
- **"Recent sold comps near X"** — `zillow-listing --type sold --keyword "X" --days-on-zillow 12m`.
- **"Track this product's price"** — Loop `amazon-product --asin X` on a schedule; persist `.price` to a file.
- **"What's trending around X?"** — `google-trends --q "X"` for relative interest; `google-news --q "X"` for headlines.
- **"Find businesses near me that do X"** — `google-maps --q "X" --ll "@LAT,LNG,12z"` then fan out `google-maps-place` for contacts.
- **"How does this look in country Y?"** — `--gl Y` on SERP commands, `--proxy-country Y` on `web-scraping`. Useful for geo-targeted SEO checks, geo-blocked content.
- **"Pull structured data from this page"** — `web-scraping --ai-extract-rules-json '{"price": {"type": "number"}, ...}'`. Works on arbitrary pages without writing CSS selectors.
- **"List of items → per-item details"** — Pattern: search command produces IDs/URLs, pipe through `xargs` into the matching `*-property` / `*-product` / `*-place` deep-dive command.
- **"Find this person's role / employer / LinkedIn / followers"** — `google-serp --q '"Person Name" linkedin'` first. The organic-result title is typically `Name — Role at Company | LinkedIn` and the snippet carries location, headline, connection count. SERP often answers the whole question without ever opening the profile page.
- **"What is company X doing? Where's their HQ? Who works there?"** — `google-serp --q "$COMPANY"` returns a `.knowledge_graph` block with founder, HQ, founded year, parent, employee range — pre-extracted. `google-news --q "$COMPANY"` for recent activity. Specific facts via targeted SERP: `--q '"$COMPANY" headquarters'`, `--q '"$COMPANY" funding'`, `--q 'site:linkedin.com/company "$COMPANY"'`.
- **"Find emails for company X" / "personal email for person Y"** — start with SERP: `--q '"@example.com"'` or `--q '"jane@example.com"'` often surfaces actual emails indexed by Google. Pattern-guess + SERP-verify for individuals. Disclose unverified guesses to the user.
- **"Enrich this CSV of leads"** — per row: `google-serp` for LinkedIn, role, employer; another SERP to verify email or pattern. Stay in SERP unless a specific field is missing.
- **Reverse-lookup (email / phone / domain → identity)** — `google-serp` with the literal value in quotes (`--q '"jane@x.com"'`, `--q '"+1 555 123 4567"'`, `--q '"acme corp" site:example.com'`) almost always surfaces the matching person or business.
**SERP-first principle**: for any data-enrichment intent (people, companies, emails, products, places), reach for `google-serp` / `google-news` / `google-shopping` / `google-maps` first. They return Google's already-extracted structured fields (`.knowledge_graph`, `.organic_results[].snippet`, `.local_results[]`, etc.) and bypass anti-bot. Only escalate to `web-scraping` when SERP doesn't surface the specific field you need — it's the last resort, not the default. See `references/enrichment.md`.
If a user request matches one of the above and you don't invoke hasdata, you're probably hallucinating a stale answer.
## Universal flag patterns
- **Kebab-case** flag names. The CLI maps them back to the original camelCase before sending to the API.
- **Booleans defaulting to `true`** have a paired negation: `--no-block-ads`, `--no-screenshot`, `--no-js-rendering`, `--no-extract-emails`, `--no-block-resources`. Setting both `--block-ads` and `--no-block-ads` errors.
- **Anything ending in `-json`** accepts:
- inline JSON: `--extract-rules-json '{"title":"h1"}'`
- file: `--extract-rules-json @rules.json`
- stdin: `cat rules.json | hasdata web-scraping ... --extract-rules-json -`
- **Repeatable key=value** flags split on the first `=` (so values containing `=` survive): `--headers User-Agent=foo --headers Cookie=session=abc`. Pair with `--headers-json` for a JSON base; kv items override per key.
- **List flags** accept either repeats or comma-joined: `--lr lang_en --lr lang_fr` or `--lr lang_en,lang_fr`. Serialized as `key[]=value` for GET endpoints.
- **Enum flags** validate client-side. If you guess wrong, the error lists the allowed values — read the message and retry.
## Global flags (apply to every subcommand)
| Flag | Effect |
| --- | --- |
| `--raw` | Write response bytes as-is (use this when piping to `jq`) |
| `--pretty` | Pretty-print JSON (default when stdout is a TTY) |
| `-o, --output FILE` | Write response to file instead of stdout (works for binary like screenshots) |
| `--verbose` | Log outgoing URL and `X-RateLimit-*` headers to stderr |
| `--api-key KEY` | Override env var (rarely needed) |
| `--timeout DURATION` | Per-request timeout (default 2m) |
| `--retries N` | Max retries on 429/5xx (default 2) |
## Output contract
Responses are JSON. Pipe through `jq` for extraction:
```bash
hasdata google-serp --q "espresso machine" --num 10 --raw \
| jq -c '.organic_results[] | {title, link, snippet}'
```
For real-estate / e-commerce results, the array shape is API-specific — read a single response with `--pretty` first to learn the schema, then write the `jq` filter.
## Exit codes (script-safe)
| Code | Meaning |
| --- | --- |
| 0 | success |
| 1 | user / CLI-input error (missing required flag, bad enum value, missing API key) |
| 2 | network error |
| 3 | API returned 4xx (auth, quota, validation) |
| 4 | API returned 5xx |
## References
- [`references/enrichment.md`](references/enrichment.md) — **person and company enrichment** (LinkedIn lookup, emails, HQ/funding/news, CSV-row enrichment, reverse-lookup) — the highest-leverage cross-API workflows
- [`references/search.md`](references/search.md) — Google SERP / Bing / News / Trends flag catalog
- [`references/web-scraping.md`](references/web-scraping.md) — `web-scraping` flags, JS scenarios, AI extraction
- [`references/real-estate.md`](references/real-estate.md) — Zillow / Redfin / Airbnb filters and bracketed params
- [`references/ecommerce.md`](references/ecommerce.md) — Amazon / Shopify
- [`references/local-business.md`](references/local-business.md) — Maps / Yelp / YellowPages
- [`references/jobs.md`](references/jobs.md) — Indeed / Glassdoor
- [`references/all-commands.md`](references/all-commands.md) — full subcommand index with credit costs
don't have the plugin yet? install it then click "run inline in claude" again.
fetch real-time web data via the hasdata CLI. use one subcommand per API. flags and enums are derived from the live schema at api.hasdata.com/apis. reach for hasdata when the user asks about current information (prices, news, reviews, listings, job postings, social profiles, contact details) or wants to scrape a URL, summarize a page, verify a link is live, monitor a price over time, or extract structured data from arbitrary web pages.
use hasdata to ground answers in current web data instead of relying on stale training data. invoke this skill when the user asks "what does google say about X", "is this still true", "summarize this URL", "find me businesses that do X", "what's the going rate for Y", "track this product's price", "pull the latest news on Z", or explicitly requests web scraping. hasdata wraps Google, Bing, Amazon, Shopify, Zillow, Redfin, Airbnb, Yelp, YellowPages, Indeed, Glassdoor, Instagram, Google Maps/Trends/News/Images/Flights/Events APIs, and can scrape arbitrary URLs with JavaScript rendering, proxying, and AI-powered field extraction.
required:
HASDATA_API_KEY environment variable. user must run hasdata configure once, paste their key, and it saves to ~/.hasdata/config.yaml (mode 0600). every future call picks it up automatically. if missing, the CLI errors with no API key configured.hasdata binary. if not installed, run curl -sSL https://raw.githubusercontent.com/HasData/hasdata-cli/main/install.sh | sh.optional:
--api-key KEY flag to override the env var (rarely needed).--timeout DURATION to override the default 2-minute per-request timeout.--retries N to change max retries on 429/5xx (default 2).--proxy-country Y or --gl Y flags for geolocation (useful for geo-targeted SEO checks, geo-blocked content, checking how a page renders in country Y).subcommand selection context:
google-serp) or deep details on a single item (e.g., amazon-product, zillow-property).input: none (or user's hasdata API key if not yet configured).
output: CLI installed, config file at ~/.hasdata/config.yaml with mode 0600.
steps:
hasdata is installed: command -v hasdata.curl -sSL https://raw.githubusercontent.com/HasData/hasdata-cli/main/install.sh | sh.hasdata configure, paste their API key when prompted, and confirm it's saved.input: user intent (e.g., "web search", "latest news", "product prices", "maps", "real-estate", "jobs", "scrape URL", "summarize article").
output: one subcommand name (e.g., google-serp, google-news, web-scraping).
refer to the subcommand matrix below. if the user's intent is ambiguous or multi-faceted, start with the broadest match (e.g., google-serp for "what does google say about X", google-news for "latest news on X"). if the user later asks for deeper details on a single item (e.g., a specific property, product, or job listing), escalate to the matching -property, -product, or -job subcommand.
| user intent | subcommand |
|---|---|
| web search ("what does google say about...") | google-serp (full) or google-serp-light (cheap, single page) |
| latest news | google-news |
| AI mode SERP | google-ai-mode |
| shopping / product prices (broad) | google-shopping |
| shopping / product prices (Amazon-specific) | amazon-search or amazon-product |
| shopping / product prices (Shopify) | shopify-products |
| immersive product page | google-immersive-product |
| maps / places / reviews / photos | google-maps, google-maps-place, google-maps-reviews, google-maps-photos |
| Yelp / YellowPages local data | yelp-search, yelp-place, yellowpages-search, yellowpages-place |
| real-estate listings (broad) | zillow-listing, redfin-listing, airbnb-listing |
| real-estate single property deep dive | zillow-property, redfin-property, airbnb-property |
| jobs (broad) | indeed-listing, glassdoor-listing |
| jobs (single job deep dive) | indeed-job, glassdoor-job |
| Bing search | bing-serp |
| trends | google-trends |
| images | google-images |
| flights | google-flights |
| short videos | google-short-videos |
| events | google-events |
| Instagram profile | instagram-profile |
| Amazon seller | amazon-seller, amazon-seller-products |
| scrape a specific URL | web-scraping (supports JS rendering, proxies, markdown, AI extraction, screenshots) |
input: subcommand name, required flags (e.g., --q for search, --asin for product), optional flags (e.g., --num, --gl, --proxy-country).
output: a valid hasdata CLI command.
rules:
true have a negation: --no-block-ads, --no-screenshot, --no-js-rendering. do not set both --block-ads and --no-block-ads; it errors.-json accepts inline JSON (--extract-rules-json '{"title":"h1"}'), a file (--extract-rules-json @rules.json), or stdin (cat rules.json | hasdata web-scraping ... --extract-rules-json -).=, so values with = survive: --headers User-Agent=foo --headers Cookie=session=abc.--lr lang_en --lr lang_fr or --lr lang_en,lang_fr.input: constructed hasdata command, desired output format (JSON, markdown, screenshot, file).
output: raw response bytes or file written to disk.
steps:
--raw when piping to jq (skips pretty-print and TTY detection).--pretty only for human-readable terminal output.-o, --output FILE to write binary (e.g., screenshots) or large responses to a file instead of stdout.--verbose to log the outgoing URL and X-RateLimit-* headers to stderr if debugging rate limits or auth.hasdata google-serp --q "espresso machine" --num 10 --raw | jq -c '.organic_results[] | {title, link, snippet}'.input: JSON response from hasdata, jq filter expression (e.g., .organic_results[], .price, .reviews[].rating).
output: extracted fields, normalized to user's request.
steps:
--pretty to inspect the structure..organic_results[] for SERP organic results, .jobs[] for job listings, .price for product price).input: large result sets, need for multiple pages or deep dives on individual items.
output: all results aggregated into a single structure (file, stdout, or database).
steps:
--num flag (e.g., --num 100) to fetch more in a single call. check the specific subcommand's help (hasdata <api> --help) for pagination options.xargs to fan out: hasdata google-shopping --q "laptop" --num 10 --raw | jq -r '.products[].id' | xargs -I {} hasdata amazon-product --asin {} --raw..price and .timestamp to a file or database.input: exit code from hasdata, stderr output.
output: error diagnosis and next action.
interpretation:
--retries N or --timeout DURATION.hasdata <api> --help).if the user has not yet configured hasdata:
no API key configured.hasdata configure, paste their key, and confirm it's saved to ~/.hasdata/config.yaml.if the user asks "what does google say about X" or "is this still true" or "what's the latest on Y":
google-serp or google-news first. do not rely on training data cutoffs or hallucinate stale answers.-property, -place, or -job subcommand.if the user asks to "summarize this article" or "TL;DR this URL":
web-scraping --url <URL> --output-format markdown to extract clean markdown (strips ads, nav, scripts).if the user asks to "verify this link" or "is this site real":
web-scraping --url <URL> --no-block-resources to fetch the page and check the status code.--screenshot to visually inspect the page (output a PNG file with -o screenshot.png).google-serp --q 'site:example.com' to check if the domain is indexed and has any presence.if the user asks to "find alternatives to X" or "what are competitors for Y":
google-serp --q "X alternatives" or google-shopping --q "X competitors".if the user asks "what's the going rate for X" or "how much does Y cost":
google-shopping --q "<product>" to get a broad price distribution across retailers.amazon-search --q "<product>" to focus on Amazon.jq '.products[] | .price' and calculate min/max/avg if needed.if the user asks for a "phone number" or "address" for a business:
google-maps-place --place-id <ID> or yelp-place --id <ID> (already have the place ID from a prior search).if the user asks "are people happy with X service" or "is X reputable":
google-maps-reviews --place-id <ID> --sort lowest to sample negative reviews first.glassdoor-job --id <ID> to pull employer reviews if asking about a company's reputation as an employer.if the user asks "what's the salary range for Y role in Z location":
indeed-listing --q "<role>" --l "<location>" or glassdoor-listing --q "<role>" --l "<location>".jq '.jobs[] | .salary' and calculate the distribution.if the user asks to "find homes/apartments matching X criteria":
zillow-listing --q "<query>" or redfin-listing --q "<query>" or airbnb-listing --q "<query>" with location and filter flags (e.g., --price-min, --price-max, --bed-count).references/real-estate.md for the full filter catalog.if the user asks "recent sold comps near X" (real-estate):
zillow-listing --type sold --keyword "<location>" --days-on-zillow 12m.--price-min and --price-max if needed.if the user asks to "track this product's price" over time:
amazon-product --asin <ASIN> or google-shopping --url <URL> on a schedule (cron job, Lambda, systemd timer)..price and .timestamp and write to a file or database.if the user asks "what's trending around X":
google-trends --q "<topic>" for relative search interest over time.google-news --q "<topic>" for recent headlines and news velocity.if the user asks to "find businesses near me that do X":
google-maps --q "X" --ll "@LAT,LNG,12z" (substitute actual lat/lng or a place name)..local_results[] with place IDs.google-maps-place --place-id <ID> for contact details, hours, reviews on each result.if the user asks "how does this look in country Y" (geo-targeting, SEO, geo-blocked content):
--gl Y on SERP commands (e.g., google-serp --q "..." --gl fr for France-localized results).--proxy-country Y on web-scraping to render the page from country Y's IP.if the user asks to "pull structured data from this page" without writing CSS selectors:
web-scraping --url <URL> --ai-extract-rules-json '{"price": {"type": "number"}, "title": {"type": "string"}, ...}'.if the user has a "list of items → per-item details" workflow:
google-shopping) produces IDs/URLs.xargs into the matching -property, -product, or -place deep-dive subcommand.hasdata google-shopping --q "laptop" --num 10 --raw | jq -r '.products[].id' | xargs -I {} hasdata google-immersive-product --product-id {}.if the user asks to "find this person's role / employer / LinkedIn / followers":
google-serp --q '"<Person Name>" linkedin' (quoted name improves precision).Name , Role at Company | LinkedIn and the snippet carries location, headline, follower/connection count.instagram-profile or dedicated profile scraping if SERP misses the field.if the user asks "what is company X doing? where's their HQ? who works there?":
google-serp --q "<COMPANY>" to surface the .knowledge_graph block, which pre-extracts founder, HQ, founded year, parent company, employee count range.google-news --q "<COMPANY>" for recent activity and press coverage.--q '"<COMPANY>" headquarters', --q '"<COMPANY>" funding', --q 'site:linkedin.com/company "<COMPANY>"'.if the user asks to "find emails for company X" or "personal email for person Y":