HasData
Cloud platform for extracting public web data. One API key, three execution modes. All endpoints sit under https://api.hasdata.com and authenticate with the x-api-key header.
When to Use
Use this skill when:
- The user needs web scraping of arbitrary URLs.
- The user needs search engine results (Google, Bing, Trends).
- The user needs structured data extraction (ecommerce, real estate, travel, jobs, local business, YouTube).
- The user needs bulk/async crawling with webhook fan-out.
- The user explicitly asks about HasData or
api.hasdata.com.
Prerequisites
A valid HasData API key. Store it in the environment variable HASDATA_API_KEY. Never hardcode, never log.
On Windows (PowerShell), set it for the current session:
$env:HASDATA_API_KEY = "YOUR_KEY"
Or persist it for future sessions:
[Environment]::SetEnvironmentVariable("HASDATA_API_KEY", "YOUR_KEY", "User")
HTTP client with a configurable timeout of at least 300 seconds (see Pitfalls).
Network egress to https://api.hasdata.com.
Three Execution Modes
| Mode |
Latency |
When |
Endpoint |
| Web Scraping API |
seconds |
Arbitrary URL — JS rendering, CSS/AI extraction, screenshots |
POST /scrape/web |
| Scraper APIs (sync) |
seconds |
Pre-parsed JSON for known platforms (Google, Amazon, Zillow, …) |
GET /scrape/<vertical>/<resource> |
| Scraper Jobs (async) |
minutes–hours |
Bulk extraction, recursive crawling, webhook fan-out |
POST /scrapers/<slug>/jobs |
Decision rule. Default to a Scraper API when one exists for the target platform (pre-parsed JSON, no selector maintenance). Use Web Scraping for arbitrary URLs not covered by an API. Reach for a Scraper Job only when no API equivalent exists — crawler, contacts, sec-edgar, amazon-bestsellers, amazon-product-reviews — or when async fan-out + webhooks save engineering time over a paginated client loop.
Always-True Response Shape
{
"requestMetadata": { "id": "…", "status": "ok", "url": "…" },
"...": "endpoint-specific"
}
HARD RULE: Treat data as valid only if requestMetadata.status === "ok". HTTP 200 alone is not a success signal.
Procedure
1. Quick smoke test (Google SERP)
curl -G 'https://api.hasdata.com/scrape/google/serp' `
--data-urlencode 'q=coffee' `
-H 'x-api-key: YOUR_KEY'
Expected: JSON with requestMetadata.status equal to "ok".
2. Choose the execution mode
- Scraper API — if the platform has a dedicated endpoint (Google, Amazon, Zillow, Airbnb, Indeed, YouTube, etc.). Load the matching reference file (see Reference Loading Guide below) for parameters.
- Web Scraping API — for arbitrary URLs. Load
references/web-scraping.md.
- Scraper Job — for bulk/async. Load
references/scraper-jobs.md.
3. Web Scraping API (POST /scrape/web)
Load references/web-scraping.md before constructing the request.
curl -X POST 'https://api.hasdata.com/scrape/web' `
-H 'x-api-key: YOUR_KEY' `
-H 'Content-Type: application/json' `
-d '{\"url\":\"https://example.com\",\"jsRendering\":false,\"outputFormat\":\"markdown\"}'
Key parameters (full list in reference):
url — target URL (required).
jsRendering — default to false. Enable only if the page requires a headless browser.
outputFormat — markdown, html, text, or screenshot.
extract — CSS selectors or AI extraction prompt.
headers — pass custom headers including Cookie (there is no top-level cookies parameter).
4. Scraper APIs (sync, GET /scrape/<vertical>/<resource>)
Load the relevant reference file for the vertical:
curl -G 'https://api.hasdata.com/scrape/google/serp' `
--data-urlencode 'q=coffee' `
--data-urlencode 'num=10' `
-H 'x-api-key: YOUR_KEY'
Check requestMetadata.status === "ok" before consuming results. Inspect rich-snippet fields (knowledgeGraph, localResults, inlineShoppingResults, relatedQuestions) before considering direct page access.
5. Scraper Jobs (async, POST /scrapers/<slug>/jobs)
Load references/scraper-jobs.md before constructing the request.
curl -X POST 'https://api.hasdata.com/scrapers/crawler/jobs' `
-H 'x-api-key: YOUR_KEY' `
-H 'Content-Type: application/json' `
-d '{\"url\":\"https://example.com\",\"outputFormat\":[\"markdown\"],\"includePaths\":\"/docs/.+\"}'
HARD RULES for async jobs:
- The submit response handle is
body.id (an integer), not jobId. Persist it immediately.
- Poll
GET /scrapers/jobs/<id> every 10–30 s with backoff.
- Treat webhooks as best-effort (3 retries). Always pair with polling.
- On
finished, the status carries data: {csv, json, xlsx} short-lived URLs — download immediately.
6. High-leverage patterns
- SERP-first enrichment. Use Google SERP to surface public snippets for company/professional lookup before attempting direct scraping. Treat personal email/phone lookup as allowed only with a legitimate purpose and user authorization.
- AI Mode + verify.
/scrape/google/ai-mode for the answer + references → /scrape/web (markdown) on each reference URL → cited RAG context, no vector DB.
- Maps → leads.
/scrape/google-maps/search returns business websites and phones. Apply opt-out, rate, and privacy-law constraints before any outreach use.
- Crawler → corpus.
crawler Scraper Job with outputFormat: ["markdown"] + includePaths: "/docs/.+" produces an LLM-ready corpus in one submission.
- Pre-extracted via SERP rich snippets.
knowledgeGraph, localResults, inlineShoppingResults, relatedQuestions carry pre-parsed public facts. Always check them before considering direct page access.
Reference Loading Guide
Load these files on demand — when the user's request maps to a specific vertical or pattern:
| Reference file |
Load when… |
references/web-scraping.md |
Using POST /scrape/web — parameters, JS scenarios, AI extraction, cookie auth. |
references/search.md |
Google SERP / Light / AI Mode / News / Shopping / Bing / Trends + pagination. |
references/ecommerce.md |
Amazon (product, search, seller, seller-products) and Shopify. |
references/real-estate.md |
Zillow, Redfin (bracketed filters). |
references/travel.md |
Airbnb, Booking, Google Flights (occupancy rules, token pagination, IATA codes). |
references/local-business.md |
Maps (search/place/reviews/photos/posts), Yelp, YellowPages. |
references/jobs.md |
Indeed and Glassdoor. |
references/youtube.md |
YouTube search / video / channel / transcript. |
references/scraper-jobs.md |
Async submit/poll/results, Crawler, Contacts, SEC EDGAR, webhook receiver. |
references/code-recipes.md |
Ready-to-paste Python and TypeScript clients with retry, backoff, bounded concurrency, and the full job lifecycle. |
Wiring from Code
- Auth:
x-api-key header on every request. Read from HASDATA_API_KEY env. Never hardcode, never log.
- Timeouts: Set client timeout ≥ 300 s. HasData's own deadline is 300 s; shorter clients produce phantom failures while still being billed on completion.
- Retries:
429 and 5xx only — exponential backoff with jitter. Never retry 4xx (auth, validation).
- Concurrency: Cap at your plan limit. The free tier is 1; anything higher just generates
429s.
- Async jobs: Handle is
body.id (integer), not jobId. Poll GET /scrapers/jobs/<id> every 10–30 s. Webhooks are best-effort; always pair with polling. Download result URLs immediately on finished.
See references/code-recipes.md for complete Python and TypeScript client implementations.
Pitfalls
- 300 s server deadline. Match your client timeout to at least 300 s. Shorter timeouts cause phantom failures while still being billed.
requestMetadata.status === "ok" is the only success signal. HTTP 200 alone is not enough — always check the metadata status field.
- Disable
jsRendering first. Enable only if the page needs it — most static pages parse fine without a headless browser. Rendering costs more and is slower.
- No
cookies parameter. Cookies go through headers["Cookie"], not a top-level field.
includePaths regex is case-sensitive. /blog/.+ will not match /Blog/....
- Scraper Job
data is double-wrapped. Each row is body.data[i].data; the outer wrapper carries id, jobId, dataId, createdAt, updatedAt.
- Async job handle is
body.id (integer), not jobId. Persist it immediately after submit.
- Webhooks are best-effort with 3 retries. Always have a polling fallback.
- Concurrency cap. Free tier is 1 concurrent request. Exceeding your plan limit generates
429s.
- Never retry
4xx. 401 = invalid key, 403 = quota exhausted, 429 = concurrency cap. Only 429 and 5xx are retryable.
- Result URLs are short-lived. Download
csv/json/xlsx URLs immediately on job finished.
Verification
API key validity — run the smoke test and confirm requestMetadata.status === "ok":
curl -G 'https://api.hasdata.com/scrape/google/serp' `
--data-urlencode 'q=test' `
-H "x-api-key: $env:HASDATA_API_KEY"
Expected output contains: "status": "ok".
Error code mapping — verify you handle each correctly:
| HTTP |
Meaning |
Retry? |
401 |
Invalid key |
No |
403 |
Quota exhausted |
No |
429 |
Concurrency cap |
Yes (backoff) |
500 |
Server error |
Yes (backoff) |
Async job lifecycle — after POST /scrapers/<slug>/jobs, verify:
- Response contains
id (integer) — not jobId.
GET /scrapers/jobs/<id> eventually returns status finished.
data.csv, data.json, or data.xlsx URLs are present and downloadable.
Client timeout — confirm your HTTP client timeout is set to ≥ 300 s.
Resources
Limitations
- Requires access to HasData services and valid credentials.
- Data quality and available fields depend on the target website and extraction method used.
- JavaScript-heavy websites may require rendering, which can affect performance and cost.
- Use only for public data or content the user is authorized to access; respect site terms, robots/access controls, privacy law, and rate limits.
- Rate limits, quotas, and account restrictions may apply depending on the endpoint and subscription plan.
1---2name: hasdata3description: Calls HasData (api.hasdata.com, x-api-key) for Google/Bing SERP JSON, vertical scrapers (Amazon, Zillow, Maps), POST /scrape/web on arbitrary public URLs, and async Scraper Jobs with poll plus webhook. Use when the request is HasData, public SERP, or bulk public crawl. Not for authenticated first-party product APIs, CAPTCHA bypass, or Playwright/CDP sessions that never hit HasData.4license: MIT5---6
7# HasData
8
9Cloud platform for extracting public web data. One API key, three execution modes. All endpoints sit under `https://api.hasdata.com` and authenticate with the `x-api-key` header.
10
11## When to Use
12
13Use this skill when:
14
15- The user needs web scraping of arbitrary URLs.
16- The user needs search engine results (Google, Bing, Trends).
17- The user needs structured data extraction (ecommerce, real estate, travel, jobs, local business, YouTube).
18- The user needs bulk/async crawling with webhook fan-out.
19- The user explicitly asks about HasData or `api.hasdata.com`.
20
21## Prerequisites
22
23- A valid HasData API key. Store it in the environment variable `HASDATA_API_KEY`. Never hardcode, never log.
24- On Windows (PowerShell), set it for the current session:
25
26 ```powershell
27 $env:HASDATA_API_KEY = "YOUR_KEY"
28 ```
29
30 Or persist it for future sessions:
31
32 ```powershell
33 [Environment]::SetEnvironmentVariable("HASDATA_API_KEY", "YOUR_KEY", "User")
34 ```
35
36- HTTP client with a configurable timeout of **at least 300 seconds** (see Pitfalls).
37- Network egress to `https://api.hasdata.com`.
38
39## Three Execution Modes
40
41| Mode | Latency | When | Endpoint |
42|---|---|---|---|
43| **Web Scraping API** | seconds | Arbitrary URL — JS rendering, CSS/AI extraction, screenshots | `POST /scrape/web` |
44| **Scraper APIs** (sync) | seconds | Pre-parsed JSON for known platforms (Google, Amazon, Zillow, …) | `GET /scrape/<vertical>/<resource>` |
45| **Scraper Jobs** (async) | minutes–hours | Bulk extraction, recursive crawling, webhook fan-out | `POST /scrapers/<slug>/jobs` |
46
47**Decision rule.** Default to a **Scraper API** when one exists for the target platform (pre-parsed JSON, no selector maintenance). Use **Web Scraping** for arbitrary URLs not covered by an API. Reach for a **Scraper Job** only when no API equivalent exists — `crawler`, `contacts`, `sec-edgar`, `amazon-bestsellers`, `amazon-product-reviews` — *or* when async fan-out + webhooks save engineering time over a paginated client loop.
48
49## Always-True Response Shape
50
51```json
52{
53 "requestMetadata": { "id": "…", "status": "ok", "url": "…" },
54 "...": "endpoint-specific"
55}
56```
57
58**HARD RULE:** Treat data as valid only if `requestMetadata.status === "ok"`. HTTP 200 alone is **not** a success signal.
59
60## Procedure
61
62### 1. Quick smoke test (Google SERP)
63
64```powershell
65curl -G 'https://api.hasdata.com/scrape/google/serp' `
66 --data-urlencode 'q=coffee' `
67 -H 'x-api-key: YOUR_KEY'
68```
69
70Expected: JSON with `requestMetadata.status` equal to `"ok"`.
71
72### 2. Choose the execution mode
73
74- **Scraper API** — if the platform has a dedicated endpoint (Google, Amazon, Zillow, Airbnb, Indeed, YouTube, etc.). Load the matching reference file (see Reference Loading Guide below) for parameters.
75- **Web Scraping API** — for arbitrary URLs. Load `references/web-scraping.md`.
76- **Scraper Job** — for bulk/async. Load `references/scraper-jobs.md`.
77
78### 3. Web Scraping API (`POST /scrape/web`)
79
80Load `references/web-scraping.md` before constructing the request.
81
82```powershell
83curl -X POST 'https://api.hasdata.com/scrape/web' `
84 -H 'x-api-key: YOUR_KEY' `
85 -H 'Content-Type: application/json' `
86 -d '{\"url\":\"https://example.com\",\"jsRendering\":false,\"outputFormat\":\"markdown\"}'
87```
88
89Key parameters (full list in reference):
90
91- `url` — target URL (required).
92- `jsRendering` — **default to `false`**. Enable only if the page requires a headless browser.
93- `outputFormat` — `markdown`, `html`, `text`, or `screenshot`.
94- `extract` — CSS selectors or AI extraction prompt.
95- `headers` — pass custom headers including `Cookie` (there is **no** top-level `cookies` parameter).
96
97### 4. Scraper APIs (sync, `GET /scrape/<vertical>/<resource>`)
98
99Load the relevant reference file for the vertical:
100
101```powershell
102curl -G 'https://api.hasdata.com/scrape/google/serp' `
103 --data-urlencode 'q=coffee' `
104 --data-urlencode 'num=10' `
105 -H 'x-api-key: YOUR_KEY'
106```
107
108Check `requestMetadata.status === "ok"` before consuming results. Inspect rich-snippet fields (`knowledgeGraph`, `localResults`, `inlineShoppingResults`, `relatedQuestions`) before considering direct page access.
109
110### 5. Scraper Jobs (async, `POST /scrapers/<slug>/jobs`)
111
112Load `references/scraper-jobs.md` before constructing the request.
113
114```powershell
115curl -X POST 'https://api.hasdata.com/scrapers/crawler/jobs' `
116 -H 'x-api-key: YOUR_KEY' `
117 -H 'Content-Type: application/json' `
118 -d '{\"url\":\"https://example.com\",\"outputFormat\":[\"markdown\"],\"includePaths\":\"/docs/.+\"}'
119```
120
121**HARD RULES for async jobs:**
122
1231. The submit response handle is `body.id` (an **integer**), **not** `jobId`. Persist it immediately.
1242. Poll `GET /scrapers/jobs/<id>` every 10–30 s with backoff.
1253. Treat webhooks as **best-effort** (3 retries). Always pair with polling.
1264. On `finished`, the status carries `data: {csv, json, xlsx}` short-lived URLs — **download immediately**.
127
128### 6. High-leverage patterns
129
130- **SERP-first enrichment.** Use Google SERP to surface public snippets for company/professional lookup before attempting direct scraping. Treat personal email/phone lookup as allowed only with a legitimate purpose and user authorization.
131- **AI Mode + verify.** `/scrape/google/ai-mode` for the answer + references → `/scrape/web` (markdown) on each reference URL → cited RAG context, no vector DB.
132- **Maps → leads.** `/scrape/google-maps/search` returns business websites and phones. Apply opt-out, rate, and privacy-law constraints before any outreach use.
133- **Crawler → corpus.** `crawler` Scraper Job with `outputFormat: ["markdown"]` + `includePaths: "/docs/.+"` produces an LLM-ready corpus in one submission.
134- **Pre-extracted via SERP rich snippets.** `knowledgeGraph`, `localResults`, `inlineShoppingResults`, `relatedQuestions` carry pre-parsed public facts. Always check them before considering direct page access.
135
136## Reference Loading Guide
137
138Load these files **on demand** — when the user's request maps to a specific vertical or pattern:
139
140| Reference file | Load when… |
141|---|---|
142| `references/web-scraping.md` | Using `POST /scrape/web` — parameters, JS scenarios, AI extraction, cookie auth. |
143| `references/search.md` | Google SERP / Light / AI Mode / News / Shopping / Bing / Trends + pagination. |
144| `references/ecommerce.md` | Amazon (product, search, seller, seller-products) and Shopify. |
145| `references/real-estate.md` | Zillow, Redfin (bracketed filters). |
146| `references/travel.md` | Airbnb, Booking, Google Flights (occupancy rules, token pagination, IATA codes). |
147| `references/local-business.md` | Maps (search/place/reviews/photos/posts), Yelp, YellowPages. |
148| `references/jobs.md` | Indeed and Glassdoor. |
149| `references/youtube.md` | YouTube search / video / channel / transcript. |
150| `references/scraper-jobs.md` | Async submit/poll/results, Crawler, Contacts, SEC EDGAR, webhook receiver. |
151| `references/code-recipes.md` | Ready-to-paste Python and TypeScript clients with retry, backoff, bounded concurrency, and the full job lifecycle. |
152
153## Wiring from Code
154
155- **Auth:** `x-api-key` header on every request. Read from `HASDATA_API_KEY` env. Never hardcode, never log.
156- **Timeouts:** Set client timeout **≥ 300 s**. HasData's own deadline is 300 s; shorter clients produce phantom failures while still being billed on completion.
157- **Retries:** `429` and `5xx` only — exponential backoff with jitter. **Never retry `4xx`** (auth, validation).
158- **Concurrency:** Cap at your plan limit. The free tier is **1**; anything higher just generates `429`s.
159- **Async jobs:** Handle is `body.id` (integer), not `jobId`. Poll `GET /scrapers/jobs/<id>` every 10–30 s. Webhooks are best-effort; always pair with polling. Download result URLs immediately on `finished`.
160
161See `references/code-recipes.md` for complete Python and TypeScript client implementations.
162
163## Pitfalls
164
165- **300 s server deadline.** Match your client timeout to at least 300 s. Shorter timeouts cause phantom failures while still being billed.
166- **`requestMetadata.status === "ok"` is the only success signal.** HTTP 200 alone is not enough — always check the metadata status field.
167- **Disable `jsRendering` first.** Enable only if the page needs it — most static pages parse fine without a headless browser. Rendering costs more and is slower.
168- **No `cookies` parameter.** Cookies go through `headers["Cookie"]`, not a top-level field.
169- **`includePaths` regex is case-sensitive.** `/blog/.+` will not match `/Blog/...`.
170- **Scraper Job `data` is double-wrapped.** Each row is `body.data[i].data`; the outer wrapper carries `id`, `jobId`, `dataId`, `createdAt`, `updatedAt`.
171- **Async job handle is `body.id` (integer), not `jobId`.** Persist it immediately after submit.
172- **Webhooks are best-effort with 3 retries.** Always have a polling fallback.
173- **Concurrency cap.** Free tier is 1 concurrent request. Exceeding your plan limit generates `429`s.
174- **Never retry `4xx`.** `401` = invalid key, `403` = quota exhausted, `429` = concurrency cap. Only `429` and `5xx` are retryable.
175- **Result URLs are short-lived.** Download `csv`/`json`/`xlsx` URLs immediately on job `finished`.
176
177## Verification
178
1791. **API key validity** — run the smoke test and confirm `requestMetadata.status === "ok"`:
180
181 ```powershell
182 curl -G 'https://api.hasdata.com/scrape/google/serp' `
183 --data-urlencode 'q=test' `
184 -H "x-api-key: $env:HASDATA_API_KEY"
185 ```
186
187 Expected output contains: `"status": "ok"`.
188
1892. **Error code mapping** — verify you handle each correctly:
190
191 | HTTP | Meaning | Retry? |
192 |---|---|---|
193 | `401` | Invalid key | No |
194 | `403` | Quota exhausted | No |
195 | `429` | Concurrency cap | Yes (backoff) |
196 | `500` | Server error | Yes (backoff) |
197
1983. **Async job lifecycle** — after `POST /scrapers/<slug>/jobs`, verify:
199 - Response contains `id` (integer) — not `jobId`.
200 - `GET /scrapers/jobs/<id>` eventually returns status `finished`.
201 - `data.csv`, `data.json`, or `data.xlsx` URLs are present and downloadable.
202
2034. **Client timeout** — confirm your HTTP client timeout is set to **≥ 300 s**.
204
205## Resources
206
207- Sitemap: <https://docs.hasdata.com/llms.txt>
208- API status codes: <https://docs.hasdata.com/api-codes>
209- Credits & concurrency: <https://docs.hasdata.com/credits-and-concurrency>
210- Dashboard: <https://app.hasdata.com>
211
212## Limitations
213
214- Requires access to HasData services and valid credentials.
215- Data quality and available fields depend on the target website and extraction method used.
216- JavaScript-heavy websites may require rendering, which can affect performance and cost.
217- Use only for public data or content the user is authorized to access; respect site terms, robots/access controls, privacy law, and rate limits.
218- Rate limits, quotas, and account restrictions may apply depending on the endpoint and subscription plan.