opencode-skills-collection 3.0.36 → 3.0.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled-skills/.antigravity-install-manifest.json +13 -1
- package/bundled-skills/2slides-ppt-generator/SKILL.md +786 -0
- package/bundled-skills/2slides-ppt-generator/references/api-reference.md +499 -0
- package/bundled-skills/2slides-ppt-generator/references/mcp-integration.md +282 -0
- package/bundled-skills/2slides-ppt-generator/references/pricing.md +195 -0
- package/bundled-skills/2slides-ppt-generator/scripts/api_constants.py +87 -0
- package/bundled-skills/2slides-ppt-generator/scripts/create_pdf_slides.py +159 -0
- package/bundled-skills/2slides-ppt-generator/scripts/download_slides_pages_voices.py +157 -0
- package/bundled-skills/2slides-ppt-generator/scripts/generate_narration.py +197 -0
- package/bundled-skills/2slides-ppt-generator/scripts/generate_slides.py +247 -0
- package/bundled-skills/2slides-ppt-generator/scripts/get_job_status.py +106 -0
- package/bundled-skills/2slides-ppt-generator/scripts/search_themes.py +137 -0
- package/bundled-skills/anti-sycophancy/README.md +86 -0
- package/bundled-skills/anti-sycophancy/SKILL.md +40 -0
- package/bundled-skills/antigravity-agent-manager/SKILL.md +112 -0
- package/bundled-skills/docs/integrations/jetski-cortex.md +3 -3
- package/bundled-skills/docs/integrations/jetski-gemini-loader/README.md +1 -1
- package/bundled-skills/docs/maintainers/repo-growth-seo.md +3 -3
- package/bundled-skills/docs/maintainers/skills-update-guide.md +1 -1
- package/bundled-skills/docs/sources/sources.md +1 -0
- package/bundled-skills/docs/users/bundles.md +1 -1
- package/bundled-skills/docs/users/claude-code-skills.md +1 -1
- package/bundled-skills/docs/users/gemini-cli-skills.md +1 -1
- package/bundled-skills/docs/users/getting-started.md +1 -1
- package/bundled-skills/docs/users/kiro-integration.md +1 -1
- package/bundled-skills/docs/users/usage.md +4 -4
- package/bundled-skills/docs/users/visual-guide.md +4 -4
- package/bundled-skills/event-staffing-compliance/SKILL.md +91 -0
- package/bundled-skills/event-staffing-ordering/SKILL.md +119 -0
- package/bundled-skills/examprep-ai/SKILL.md +446 -0
- package/bundled-skills/hasdata/SKILL.md +107 -0
- package/bundled-skills/hasdata/references/code-recipes.md +150 -0
- package/bundled-skills/hasdata/references/ecommerce.md +116 -0
- package/bundled-skills/hasdata/references/jobs.md +111 -0
- package/bundled-skills/hasdata/references/local-business.md +145 -0
- package/bundled-skills/hasdata/references/real-estate.md +84 -0
- package/bundled-skills/hasdata/references/scraper-jobs.md +252 -0
- package/bundled-skills/hasdata/references/search.md +154 -0
- package/bundled-skills/hasdata/references/travel.md +202 -0
- package/bundled-skills/hasdata/references/web-scraping.md +159 -0
- package/bundled-skills/hasdata/references/youtube.md +186 -0
- package/bundled-skills/hasdata-cli/SKILL.md +169 -0
- package/bundled-skills/hasdata-cli/references/all-commands.md +107 -0
- package/bundled-skills/hasdata-cli/references/ecommerce.md +106 -0
- package/bundled-skills/hasdata-cli/references/enrichment.md +227 -0
- package/bundled-skills/hasdata-cli/references/jobs.md +84 -0
- package/bundled-skills/hasdata-cli/references/local-business.md +123 -0
- package/bundled-skills/hasdata-cli/references/real-estate.md +126 -0
- package/bundled-skills/hasdata-cli/references/search.md +122 -0
- package/bundled-skills/hasdata-cli/references/travel.md +102 -0
- package/bundled-skills/hasdata-cli/references/web-scraping.md +181 -0
- package/bundled-skills/hasdata-cli/references/youtube.md +145 -0
- package/bundled-skills/linkedin-content-generator/SKILL.md +492 -0
- package/bundled-skills/linkedin-content-generator/scripts/generate_calendar.py +82 -0
- package/bundled-skills/linkedin-content-generator/scripts/generate_carousel.py +69 -0
- package/bundled-skills/linkedin-content-generator/scripts/generate_newsletter.py +64 -0
- package/bundled-skills/linkedin-content-generator/scripts/generate_post.py +77 -0
- package/bundled-skills/linkedin-content-generator/scripts/memory.md +49 -0
- package/bundled-skills/linkedin-content-generator/scripts/memory_manager.py +134 -0
- package/bundled-skills/linkedin-content-generator/scripts/utils.py +96 -0
- package/bundled-skills/permission-manager/README.md +22 -0
- package/bundled-skills/permission-manager/SKILL.md +54 -0
- package/bundled-skills/skill-suggester/README.md +14 -0
- package/bundled-skills/skill-suggester/SKILL.md +69 -0
- package/bundled-skills/smart-git-automation/README.md +31 -0
- package/bundled-skills/smart-git-automation/SKILL.md +96 -0
- package/bundled-skills/vercel-optimize/lib/cost-coverage.mjs +3 -1
- package/bundled-skills/vercel-optimize/lib/render-report.mjs +2 -2
- package/bundled-skills/vercel-optimize/lib/util.mjs +7 -0
- package/bundled-skills/vercel-optimize/lib/verify-claim.mjs +2 -7
- package/bundled-skills/vercel-optimize/lib/workspace-resolver.mjs +2 -1
- package/package.json +2 -2
- package/skills_index.json +268 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# Web Scraping API — `POST /scrape/web`
|
|
2
|
+
|
|
3
|
+
One endpoint to fetch any URL, optionally with JS rendering, proxies, AI extraction, and screenshots. Synchronous.
|
|
4
|
+
|
|
5
|
+
> Reach for this only when the user gave you a specific URL, or when no Scraper API covers the field. Otherwise the platform-specific APIs return pre-extracted JSON without direct page access. Use only for public pages or content the user is authorized to access.
|
|
6
|
+
|
|
7
|
+
## Minimal request
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
import requests
|
|
11
|
+
|
|
12
|
+
# Multiple outputs (or include "json") → response is a JSON object
|
|
13
|
+
resp = requests.post(
|
|
14
|
+
"https://api.hasdata.com/scrape/web",
|
|
15
|
+
headers={"x-api-key": API_KEY},
|
|
16
|
+
json={"url": "https://example.com", "outputFormat": ["markdown", "json"]},
|
|
17
|
+
timeout=300,
|
|
18
|
+
)
|
|
19
|
+
data = resp.json()
|
|
20
|
+
assert data["requestMetadata"]["status"] == "ok"
|
|
21
|
+
print(data["markdown"])
|
|
22
|
+
|
|
23
|
+
# Single non-JSON output → response IS the raw content (markdown/html/text bytes)
|
|
24
|
+
resp = requests.post(
|
|
25
|
+
"https://api.hasdata.com/scrape/web",
|
|
26
|
+
headers={"x-api-key": API_KEY},
|
|
27
|
+
json={"url": "https://example.com", "outputFormat": ["markdown"]},
|
|
28
|
+
timeout=300,
|
|
29
|
+
)
|
|
30
|
+
print(resp.text) # raw markdown — no JSON parsing
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Body parameters
|
|
34
|
+
|
|
35
|
+
| Parameter | Type | Notes |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| `url` | string | **Required.** Absolute URL. |
|
|
38
|
+
| `outputFormat` | string[] | `html`, `text`, `markdown`, `json`. **Single non-JSON format → raw content as the body** (not JSON-wrapped); multiple formats → JSON object with one key per format. Always include `"json"` (or another format) when you also need `requestMetadata`. |
|
|
39
|
+
| `proxyType` | enum | `datacenter` (default) or `residential` — use residential only for authorized geo/availability testing where terms and access controls permit it. |
|
|
40
|
+
| `proxyCountry` | string | ISO 3166-1 alpha-2 — `US`, `UK`, `DE`, `FR`, `IT`, `SE`, `BR`, `CA`, `JP`, `SG`, `IN`, `ID`, `IE`. |
|
|
41
|
+
| `jsRendering` | bool | Headless browser — required for SPAs and dynamically-injected content. |
|
|
42
|
+
| `wait` / `waitFor` | int (ms) / CSS string | Fixed delay vs. wait-until-selector. Prefer `waitFor`. |
|
|
43
|
+
| `jsScenario` | array | Sequence of click/fill/wait/scroll/evaluate. Requires `jsRendering`. |
|
|
44
|
+
| `headers` | object | Custom headers. **Cookies go here too — no separate `cookies` parameter.** |
|
|
45
|
+
| `screenshot` | bool | Returns a CDN URL in the response. |
|
|
46
|
+
| `extractRules` | object | CSS selectors → field text. `@attr` for attributes. **First match only**, missing → `null`. |
|
|
47
|
+
| `aiExtractRules` | object | Typed LLM extraction. Types: `string`, `number`, `boolean`, `list`, `item`. |
|
|
48
|
+
| `extractEmails` / `extractLinks` | bool | Quick helpers. |
|
|
49
|
+
| `blockResources` / `blockAds` | bool | Skip images/CSS/ads — speeds text-only scrapes. |
|
|
50
|
+
| `blockUrls` | string[] | Glob patterns to block subresources. |
|
|
51
|
+
| `removeBase64Images` | bool | Strip inline base64 from response. |
|
|
52
|
+
| `includeOnlyTags` / `excludeTags` | string[] | Trim DOM before serialization. |
|
|
53
|
+
|
|
54
|
+
## CSS extraction (`extractRules`)
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
"extractRules": {
|
|
58
|
+
"title": "h1",
|
|
59
|
+
"links": "a @href", # @attr extracts attribute
|
|
60
|
+
"price": ".price-now",
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
First match per selector. For lists of records, use `aiExtractRules` with `type: "list"`.
|
|
65
|
+
|
|
66
|
+
## AI extraction (`aiExtractRules`)
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
"aiExtractRules": {
|
|
70
|
+
"title": {"type": "string"},
|
|
71
|
+
"price": {"type": "number"},
|
|
72
|
+
"in_stock": {"type": "boolean"},
|
|
73
|
+
"tags": {"type": "list", "description": "category tags"},
|
|
74
|
+
"author": {"type": "item", "output": {
|
|
75
|
+
"name": {"type": "string"},
|
|
76
|
+
"verified": {"type": "boolean"},
|
|
77
|
+
}},
|
|
78
|
+
"reviews": {"type": "list", "output": {
|
|
79
|
+
"rating": {"type": "number"},
|
|
80
|
+
"text": {"type": "string"},
|
|
81
|
+
}},
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Use when layout varies across pages; otherwise prefer `extractRules` for determinism and predictability.
|
|
86
|
+
|
|
87
|
+
## JS scenarios
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
"jsScenario": [
|
|
91
|
+
{"fill": ["#email", "user@example.com"]},
|
|
92
|
+
{"fill": ["#password", PASSWORD]},
|
|
93
|
+
{"click": "#login"},
|
|
94
|
+
{"waitFor": ".dashboard"},
|
|
95
|
+
{"scrollY": 2000},
|
|
96
|
+
{"waitForAndClick": ".load-more"},
|
|
97
|
+
{"evaluate": "window.__APP_STATE__"},
|
|
98
|
+
]
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Actions: `click`, `fill: [sel, val]`, `wait: ms`, `waitFor: sel`, `waitForAndClick: sel`, `scrollX/scrollY: px`, `evaluate: "JS"`. Sequential. Missing element on `click`/`fill` fails the request — wrap with `waitFor` first.
|
|
102
|
+
|
|
103
|
+
## Auth via cookies
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
"headers": {
|
|
107
|
+
"User-Agent": "Mozilla/5.0 ...",
|
|
108
|
+
"Cookie": "session=abc; csrf=xyz",
|
|
109
|
+
"Accept-Language": "en-US,en;q=0.9",
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Capture cookies once in a real browser (devtools → Storage → Cookies), forward via the `Cookie` header. Only with explicit user permission and authority to access that account/content; never use cookies to bypass someone else's access controls.
|
|
114
|
+
|
|
115
|
+
## Slim response & speed
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
{
|
|
119
|
+
"blockResources": True, # skip images/CSS/fonts
|
|
120
|
+
"blockAds": True, # skip ad/tracking
|
|
121
|
+
"blockUrls": ["**.googletagmanager.com/**", "**.doubleclick.net/**"],
|
|
122
|
+
"removeBase64Images": True,
|
|
123
|
+
"excludeTags": ["script", "style", "nav", "footer"],
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Reduces response size 60–90% on noisy pages.
|
|
128
|
+
|
|
129
|
+
## Response shape
|
|
130
|
+
|
|
131
|
+
The wrapper is JSON **only when** the response is JSON-wrapped — i.e. multiple `outputFormat` values, or a single value that includes `"json"`. With a single non-JSON format the response body is the raw content (`text/markdown`, `text/html`, `text/plain`).
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"requestMetadata": { "id": "uuid", "status": "ok", "url": "..." },
|
|
136
|
+
"headers": { "content-type": "text/html" },
|
|
137
|
+
"screenshot": "https://...jpeg",
|
|
138
|
+
"content": "<!DOCTYPE html>...", // outputFormat: html
|
|
139
|
+
"markdown": "# Title\n...", // outputFormat: markdown
|
|
140
|
+
"text": "Title\n...",
|
|
141
|
+
"extractRules": { ... }, // present iff sent
|
|
142
|
+
"aiExtractRules": { ... }, // present iff sent
|
|
143
|
+
"extractedEmails": [ ... ], // iff extractEmails: true
|
|
144
|
+
"extractedLinks": [ ... ] // iff extractLinks: true
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Batch (`POST /scrape/batch/web`)
|
|
149
|
+
|
|
150
|
+
Async wrapper for >1k URLs running the same extraction. Returns `jobId`; poll status, page `/results`. Per-batch cap **10,000 URLs**. For small workloads loop the sync endpoint at concurrency = plan limit.
|
|
151
|
+
|
|
152
|
+
## Gotchas
|
|
153
|
+
|
|
154
|
+
- **Disable `jsRendering` first**, enable only when the page needs it — most static pages parse fine without a headless browser.
|
|
155
|
+
- **`waitFor` > `wait`.** Selector-based waits adapt to network speed.
|
|
156
|
+
- **Cookies via `headers["Cookie"]` only.**
|
|
157
|
+
- **`extractRules` returns first match** — for arrays use `aiExtractRules` `type: "list"`.
|
|
158
|
+
- **Set client timeout ≥ 300 s** to match the server deadline.
|
|
159
|
+
- **`requestMetadata.status === "ok"` is the only success signal.**
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# YouTube APIs
|
|
2
|
+
|
|
3
|
+
| Endpoint | Returns |
|
|
4
|
+
|---|---|
|
|
5
|
+
| `/scrape/youtube/search` | Search results — videos, shorts, channels, playlists |
|
|
6
|
+
| `/scrape/youtube/video` | Single video metadata (stats, captions, related) |
|
|
7
|
+
| `/scrape/youtube/channel` | Channel home / videos / shorts / playlists / community |
|
|
8
|
+
| `/scrape/youtube/transcript` | Full transcript with millisecond offsets |
|
|
9
|
+
|
|
10
|
+
All synchronous `GET`. 10 credits each.
|
|
11
|
+
|
|
12
|
+
## YouTube Search
|
|
13
|
+
|
|
14
|
+
```python
|
|
15
|
+
import requests
|
|
16
|
+
|
|
17
|
+
resp = requests.get(
|
|
18
|
+
"https://api.hasdata.com/scrape/youtube/search",
|
|
19
|
+
headers={"x-api-key": API_KEY},
|
|
20
|
+
params={"q": "anthropic claude", "sortBy": "views", "date": "month"},
|
|
21
|
+
timeout=300,
|
|
22
|
+
)
|
|
23
|
+
for v in resp.json().get("videoResults", []):
|
|
24
|
+
print(v["title"], v.get("extractedViews"), v["link"])
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Query parameters
|
|
28
|
+
|
|
29
|
+
| Param | Notes |
|
|
30
|
+
|---|---|
|
|
31
|
+
| `q` | **Required.** Free-text query. |
|
|
32
|
+
| `sortBy` | `relevance` (default), `date`, `views`, `rating`, `popularity`. |
|
|
33
|
+
| `date` | Upload window: `hour`, `today`, `week`, `month`, `year`. |
|
|
34
|
+
| `length` | Duration bucket: `under4`, `between420`, `plus20`. |
|
|
35
|
+
| `videoType` | `video`, `shorts`, `channel`, `playlist`, `movie`. |
|
|
36
|
+
| `filters[]` | Feature flags ANDed: `hd`, `k4`, `hdr`, `subtitles`, `cc`, `d3`, `d360`, `vr180`, `live`, `bought`, `location`. |
|
|
37
|
+
| `gl` / `hl` | Two-letter country / language codes. |
|
|
38
|
+
| `deviceType` | `desktop`, `mobile`. |
|
|
39
|
+
| `paginationToken` | Opaque cursor from the previous `pagination.nextPageToken`. |
|
|
40
|
+
| `sp` | Raw YouTube `sp=` token (overrides `sortBy`, `date`, `videoType`, `length`, `filters[]`). |
|
|
41
|
+
|
|
42
|
+
Response: `videoResults`, `shortsResults`, `channelResults`, `playlistResults`, `adsResults`, `sponsoredResults`, `searchInformation`, `pagination`.
|
|
43
|
+
|
|
44
|
+
Per-video result keys (verified live): `videoId`, `title`, `link`, `channel`, `description`, `length`, `views`, `viewsOriginal`, `publishedDate`, `thumbnail`, `positionOnPage`. `channel` is an object — read `.channel.name` and `.channel.link`.
|
|
45
|
+
|
|
46
|
+
## YouTube Video
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
resp = requests.get(
|
|
50
|
+
"https://api.hasdata.com/scrape/youtube/video",
|
|
51
|
+
headers={"x-api-key": API_KEY},
|
|
52
|
+
params={"v": "dQw4w9WgXcQ"},
|
|
53
|
+
timeout=300,
|
|
54
|
+
)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
| Param | Notes |
|
|
58
|
+
|---|---|
|
|
59
|
+
| `v` | **Required.** 11-character YouTube video ID — the `v=` query value. |
|
|
60
|
+
| `gl` / `hl` | Country / language. |
|
|
61
|
+
| `deviceType` | `desktop` / `mobile`. |
|
|
62
|
+
|
|
63
|
+
Top-level keys: `videoId`, `title`, `description`, `channel`, `views`, `extractedViews`, `likes`, `extractedLikes`, `lengthSeconds`, `publishedDate`, `keywords`, `captions`, `socialLinks`, `music`, `category`, `thumbnail`, `isFamilySafe`, `isUnlisted`, `relatedVideos`, `relatedShorts`, `endScreenVideos`, `requestMetadata`.
|
|
64
|
+
|
|
65
|
+
Use `extractedViews` / `extractedLikes` (integers) for math; `views` / `likes` are the formatted strings.
|
|
66
|
+
|
|
67
|
+
## YouTube Channel
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
resp = requests.get(
|
|
71
|
+
"https://api.hasdata.com/scrape/youtube/channel",
|
|
72
|
+
headers={"x-api-key": API_KEY},
|
|
73
|
+
params={"channelId": "@MrBeast", "tab": "videos"},
|
|
74
|
+
timeout=300,
|
|
75
|
+
)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
| Param | Notes |
|
|
79
|
+
|---|---|
|
|
80
|
+
| `channelId` | **Required.** `@handle`, canonical `UC…` ID, or legacy `/c/<custom>` / `/user/<name>` slug. |
|
|
81
|
+
| `tab` | `featured` (default), `videos`, `shorts`, `streams`, `playlists`, `posts` / `community`, `podcasts`, `releases`, `about`, `store`. |
|
|
82
|
+
| `paginationToken` | Cursor for tabs that paginate. |
|
|
83
|
+
| `gl` / `hl` / `deviceType` | Standard. |
|
|
84
|
+
|
|
85
|
+
Response: `channelInfo`, `featuredVideo`, `sections[]`.
|
|
86
|
+
|
|
87
|
+
`channelInfo` (verified live): `name`, `handle`, `channelId`, `channelUrl`, `avatar`, `banner`, `description`, `subscribers`, `extractedSubscribers`, `videosCount`, `extractedVideosCount`, `keywords[]`, `availableTabs[]`, `verified`, `websiteUrl`, `rssUrl`, `isFamilySafe`.
|
|
88
|
+
|
|
89
|
+
`sections[]` each have `title` + `items[]` — shape depends on the tab. Iterate generically:
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
for sec in resp.json().get("sections", []):
|
|
93
|
+
for item in sec.get("items", []):
|
|
94
|
+
...
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## YouTube Transcript
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
resp = requests.get(
|
|
101
|
+
"https://api.hasdata.com/scrape/youtube/transcript",
|
|
102
|
+
headers={"x-api-key": API_KEY},
|
|
103
|
+
params={"v": "dQw4w9WgXcQ", "languageCode": "en"},
|
|
104
|
+
timeout=300,
|
|
105
|
+
)
|
|
106
|
+
text = " ".join(seg["snippet"] for seg in resp.json().get("transcript", []))
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
| Param | Notes |
|
|
110
|
+
|---|---|
|
|
111
|
+
| `v` | **Required.** 11-character video ID. |
|
|
112
|
+
| `languageCode` | BCP-47 / YouTube code (`en`, `de`, `en-US`, `pt-BR`). Must exist on the video. |
|
|
113
|
+
| `type` | `asr` to fetch the auto-generated speech-recognition track when no human captions exist. |
|
|
114
|
+
|
|
115
|
+
Response: `transcript[]` and `availableTranscripts[]`.
|
|
116
|
+
|
|
117
|
+
Each `transcript[]` entry: `startMs`, `endMs`, `snippet`, `startTimeText` (e.g. `"0:18"`).
|
|
118
|
+
|
|
119
|
+
## Patterns
|
|
120
|
+
|
|
121
|
+
### Search → video → transcript fan-out
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
def topic_corpus(query, k=5):
|
|
125
|
+
search = requests.get(
|
|
126
|
+
"https://api.hasdata.com/scrape/youtube/search",
|
|
127
|
+
headers={"x-api-key": API_KEY},
|
|
128
|
+
params={"q": query, "sortBy": "views"}, timeout=300,
|
|
129
|
+
).json()
|
|
130
|
+
docs = []
|
|
131
|
+
for v in search.get("videoResults", [])[:k]:
|
|
132
|
+
tr = requests.get(
|
|
133
|
+
"https://api.hasdata.com/scrape/youtube/transcript",
|
|
134
|
+
headers={"x-api-key": API_KEY},
|
|
135
|
+
params={"v": v["videoId"]}, timeout=300,
|
|
136
|
+
).json()
|
|
137
|
+
docs.append({
|
|
138
|
+
"videoId": v["videoId"],
|
|
139
|
+
"title": v["title"],
|
|
140
|
+
"url": v["link"],
|
|
141
|
+
"text": " ".join(s["snippet"] for s in tr.get("transcript", [])),
|
|
142
|
+
})
|
|
143
|
+
return docs
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Channel velocity
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
def channel_velocity(handle):
|
|
150
|
+
page = requests.get(
|
|
151
|
+
"https://api.hasdata.com/scrape/youtube/channel",
|
|
152
|
+
headers={"x-api-key": API_KEY},
|
|
153
|
+
params={"channelId": handle, "tab": "videos"}, timeout=300,
|
|
154
|
+
).json()
|
|
155
|
+
return [
|
|
156
|
+
{"date": it.get("publishedDate"),
|
|
157
|
+
"views": it.get("extractedViews"),
|
|
158
|
+
"title": it.get("title")}
|
|
159
|
+
for sec in page.get("sections", [])
|
|
160
|
+
for it in sec.get("items", [])
|
|
161
|
+
]
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Timestamp search inside a transcript
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
def mentions(video_id, needle):
|
|
168
|
+
tr = requests.get(
|
|
169
|
+
"https://api.hasdata.com/scrape/youtube/transcript",
|
|
170
|
+
headers={"x-api-key": API_KEY},
|
|
171
|
+
params={"v": video_id}, timeout=300,
|
|
172
|
+
).json()
|
|
173
|
+
return [(s["startTimeText"], s["snippet"])
|
|
174
|
+
for s in tr.get("transcript", [])
|
|
175
|
+
if needle.lower() in s["snippet"].lower()]
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Gotchas
|
|
179
|
+
|
|
180
|
+
- **`v` is the 11-char ID, not the URL.** Strip the `v=` value first.
|
|
181
|
+
- **`languageCode` must exist on the video.** Inspect `availableTranscripts[]` if a fetch fails, then retry.
|
|
182
|
+
- **`type=asr` is required when no human-authored caption track exists.** Otherwise the API errors on videos with auto-only captions.
|
|
183
|
+
- **`@handle` resolves to the same channel as the canonical `UC…` ID.** Prefer handles for readability.
|
|
184
|
+
- **Pagination tokens are opaque** — pass them back verbatim via `paginationToken`.
|
|
185
|
+
- **`extractedViews` / `extractedLikes`** are integers; `views` / `likes` are formatted strings. Use the integer fields for arithmetic.
|
|
186
|
+
- **`channelInfo.rssUrl`** is the canonical RSS feed for the channel — use it to subscribe in podcast clients without scraping.
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hasdata-cli
|
|
3
|
+
description: Command-line access to search, scraping, and structured web data.
|
|
4
|
+
risk: safe
|
|
5
|
+
source: official
|
|
6
|
+
source_type: official
|
|
7
|
+
source_repo: HasData/hasdata-cli
|
|
8
|
+
license: MIT
|
|
9
|
+
license_source: "https://github.com/HasData/hasdata-cli/blob/main/LICENSE"
|
|
10
|
+
date_added: "2026-06-04"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# hasdata
|
|
14
|
+
|
|
15
|
+
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`.
|
|
16
|
+
|
|
17
|
+
## When to Use
|
|
18
|
+
|
|
19
|
+
Use this skill when:
|
|
20
|
+
|
|
21
|
+
- The user wants to use the HasData CLI.
|
|
22
|
+
- The user needs current web data from the command line.
|
|
23
|
+
- The user wants to automate data collection in scripts.
|
|
24
|
+
- The user wants to retrieve search, ecommerce, travel, or local business data.
|
|
25
|
+
- The user needs web-page scraping through the CLI.
|
|
26
|
+
|
|
27
|
+
## Prerequisites
|
|
28
|
+
|
|
29
|
+
- `command -v hasdata` — if missing, download the installer from `https://raw.githubusercontent.com/HasData/hasdata-cli/main/install.sh`, inspect it, then run it locally with `sh install.sh`.
|
|
30
|
+
- 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.
|
|
31
|
+
- If a call fails with `no API key configured`, the user hasn't run `hasdata configure` yet — tell them to. **Never invent a key.**
|
|
32
|
+
|
|
33
|
+
## Quick start
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
hasdata <api> --flag value [--flag value ...] --raw | jq .
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Always pass `--raw` when piping to `jq` (skips pretty-print and TTY detection). Use `--pretty` only for human-readable terminal output.
|
|
40
|
+
|
|
41
|
+
## Picking the right subcommand
|
|
42
|
+
|
|
43
|
+
| User intent | Subcommand |
|
|
44
|
+
| --- | --- |
|
|
45
|
+
| Web search ("what does Google say about…") | `google-serp` (full features) or `google-serp-light` (cheap, single page) |
|
|
46
|
+
| Latest news | `google-news` |
|
|
47
|
+
| AI Mode SERP | `google-ai-mode` |
|
|
48
|
+
| Shopping / product prices | `google-shopping` (broad), `amazon-search` / `amazon-product` (Amazon), `shopify-products` (Shopify) |
|
|
49
|
+
| Immersive product page | `google-immersive-product` |
|
|
50
|
+
| Maps / places / reviews | `google-maps`, `google-maps-place`, `google-maps-reviews`, `google-maps-photos`, `google-maps-posts` |
|
|
51
|
+
| Yelp / YellowPages local data | `yelp-search`, `yelp-place`, `yellowpages-search`, `yellowpages-place` |
|
|
52
|
+
| Real-estate listings (homes for sale/rent/sold) | `zillow-listing`, `redfin-listing` |
|
|
53
|
+
| Real-estate single property deep dive | `zillow-property`, `redfin-property` |
|
|
54
|
+
| Travel — short-term rentals | `airbnb-listing`, `airbnb-property` |
|
|
55
|
+
| Travel — hotels / lodging | `booking-search`, `booking-place` |
|
|
56
|
+
| Travel — flights | `google-flights` |
|
|
57
|
+
| Jobs | `indeed-listing`, `indeed-job`, `glassdoor-listing`, `glassdoor-job` |
|
|
58
|
+
| Bing search | `bing-serp` |
|
|
59
|
+
| Trends | `google-trends` |
|
|
60
|
+
| Images | `google-images` |
|
|
61
|
+
| Short videos | `google-short-videos` |
|
|
62
|
+
| Events | `google-events` |
|
|
63
|
+
| YouTube search / video / channel / transcript | `youtube-search-api`, `youtube-video-api`, `youtube-channel-api`, `youtube-transcript-api` |
|
|
64
|
+
| Instagram profile | `instagram-profile` |
|
|
65
|
+
| Amazon seller | `amazon-seller`, `amazon-seller-products` |
|
|
66
|
+
| **Scrape a specific URL** | `web-scraping` — supports JS rendering, proxies, markdown output, AI extraction, screenshots |
|
|
67
|
+
|
|
68
|
+
For exact flags of a subcommand, run `hasdata <api> --help` or read the matching file in `references/`.
|
|
69
|
+
|
|
70
|
+
## Non-obvious triggers (when to reach for hasdata even if the user doesn't say "scrape")
|
|
71
|
+
|
|
72
|
+
The user often won't ask for a SERP API or a scraper directly. Map these intents to the skill:
|
|
73
|
+
|
|
74
|
+
- **"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.
|
|
75
|
+
- **"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.
|
|
76
|
+
- **"Verify this link" / "Is this site real?"** — `web-scraping --url X --no-block-resources` returns status + screenshot. Or `google-serp --q "site:example.com"`.
|
|
77
|
+
- **"What does X say about itself?"** — Pull the company's own homepage with `web-scraping --output-format markdown`, then summarize.
|
|
78
|
+
- **"Find me alternatives to X"** — `google-serp --q "X alternatives"` or `google-shopping --q "X competitors"`.
|
|
79
|
+
- **"What's the going rate for X?"** — `google-shopping` (broad) or `amazon-search` (Amazon-specific) with `jq` to extract the price distribution.
|
|
80
|
+
- **"Phone number / address for X"** — `google-maps-place` or `yelp-place`. Don't guess from training data.
|
|
81
|
+
- **"Are people happy with X service?" / "Is X reputable?"** — `google-maps-reviews --place-id ... --sort lowest` for negative samples; `glassdoor-job` for employer rep.
|
|
82
|
+
- **"What's the salary range for Y role?"** — `indeed-listing` filtered by role + location, then `jq` over `.jobs[].salary`.
|
|
83
|
+
- **"Find me homes/apartments matching X criteria"** — `zillow-listing` / `redfin-listing` / `airbnb-listing` with the corresponding filters.
|
|
84
|
+
- **"Recent sold comps near X"** — `zillow-listing --type sold --keyword "X" --days-on-zillow 12m`.
|
|
85
|
+
- **"Track this product's price"** — Loop `amazon-product --asin X` on a schedule; persist `.price` to a file.
|
|
86
|
+
- **"Summarize / cite this YouTube video"** — `youtube-transcript-api --v-param VID --raw | jq -r '.transcript[].snippet'` → feed to the summary prompt. Beats title/thumbnail-based guesses.
|
|
87
|
+
- **"Find a hotel in $CITY for $DATES under $BUDGET"** — `booking-search --keyword $CITY --check-in-date X --check-out-date Y --adults 2 --children 0 --rooms 1 --price-max $BUDGET --sort priceLowestFirst`. For one specific property, `booking-place --url ...` returns the full room/rate matrix.
|
|
88
|
+
- **"What's this channel pushing lately?"** — `youtube-channel-api --channel-id @handle --tab videos --raw | jq '.sections[].items[] | {title, publishedDate, views: .extractedViews}'`.
|
|
89
|
+
- **"Does this business have an active offer / event?"** — `google-maps-posts --place-id X --raw | jq '.posts[] | {postedAt, description, cta}'`. Surfaces current promotions Google indexed.
|
|
90
|
+
- **"What's trending around X?"** — `google-trends --q "X"` for relative interest; `google-news --q "X"` for headlines.
|
|
91
|
+
- **"Find businesses near me that do X"** — `google-maps --q "X" --ll "@LAT,LNG,12z"` then fan out `google-maps-place` for contacts.
|
|
92
|
+
- **"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.
|
|
93
|
+
- **"Pull structured data from this page"** — `web-scraping --ai-extract-rules-json '{"price": {"type": "number"}, ...}'`. Works on arbitrary pages without writing CSS selectors.
|
|
94
|
+
- **"List of items → per-item details"** — Pattern: search command produces IDs/URLs, pipe through `xargs` into the matching `*-property` / `*-product` / `*-place` deep-dive command.
|
|
95
|
+
- **"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.
|
|
96
|
+
- **"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"'`.
|
|
97
|
+
- **"Find public contact channels for company X"** — start with SERP: `--q '"@example.com"'` often surfaces publicly indexed business addresses. For personal emails or phone numbers, require a legitimate purpose, user authorization, and privacy-law/terms compliance; disclose unverified guesses.
|
|
98
|
+
- **"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.
|
|
99
|
+
- **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.
|
|
100
|
+
|
|
101
|
+
**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.) without direct access to the target site. Only escalate to `web-scraping` when SERP doesn't surface the specific field you need, the data is public or authorized, and the target's terms/access controls allow it. See `references/enrichment.md`.
|
|
102
|
+
|
|
103
|
+
If a user request matches one of the above and you don't invoke hasdata, you're probably hallucinating a stale answer.
|
|
104
|
+
|
|
105
|
+
## Universal flag patterns
|
|
106
|
+
|
|
107
|
+
- **Kebab-case** flag names. The CLI maps them back to the original camelCase before sending to the API.
|
|
108
|
+
- **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.
|
|
109
|
+
- **Anything ending in `-json`** accepts:
|
|
110
|
+
- inline JSON: `--extract-rules-json '{"title":"h1"}'`
|
|
111
|
+
- file: `--extract-rules-json @rules.json`
|
|
112
|
+
- stdin: `cat rules.json | hasdata web-scraping ... --extract-rules-json -`
|
|
113
|
+
- **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.
|
|
114
|
+
- **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.
|
|
115
|
+
- **Enum flags** validate client-side. If you guess wrong, the error lists the allowed values — read the message and retry.
|
|
116
|
+
|
|
117
|
+
## Global flags (apply to every subcommand)
|
|
118
|
+
|
|
119
|
+
| Flag | Effect |
|
|
120
|
+
| --- | --- |
|
|
121
|
+
| `--raw` | Write response bytes as-is (use this when piping to `jq`) |
|
|
122
|
+
| `--pretty` | Pretty-print JSON (default when stdout is a TTY) |
|
|
123
|
+
| `-o, --output FILE` | Write response to file instead of stdout (works for binary like screenshots) |
|
|
124
|
+
| `--verbose` | Log outgoing URL and `X-RateLimit-*` headers to stderr |
|
|
125
|
+
| `--api-key KEY` | Override env var (rarely needed) |
|
|
126
|
+
| `--timeout DURATION` | Per-request timeout (default 2m) |
|
|
127
|
+
| `--retries N` | Max retries on 429/5xx (default 2) |
|
|
128
|
+
|
|
129
|
+
## Output contract
|
|
130
|
+
|
|
131
|
+
Responses are JSON. Pipe through `jq` for extraction:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
hasdata google-serp --q "espresso machine" --num 10 --raw \
|
|
135
|
+
| jq -c '.organic_results[] | {title, link, snippet}'
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
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.
|
|
139
|
+
|
|
140
|
+
## Exit codes (script-safe)
|
|
141
|
+
|
|
142
|
+
| Code | Meaning |
|
|
143
|
+
| --- | --- |
|
|
144
|
+
| 0 | success |
|
|
145
|
+
| 1 | user / CLI-input error (missing required flag, bad enum value, missing API key) |
|
|
146
|
+
| 2 | network error |
|
|
147
|
+
| 3 | API returned 4xx (auth, quota, validation) |
|
|
148
|
+
| 4 | API returned 5xx |
|
|
149
|
+
|
|
150
|
+
## References
|
|
151
|
+
|
|
152
|
+
- [`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
|
|
153
|
+
- [`references/search.md`](references/search.md) — Google SERP / Bing / News / Trends flag catalog
|
|
154
|
+
- [`references/web-scraping.md`](references/web-scraping.md) — `web-scraping` flags, JS scenarios, AI extraction
|
|
155
|
+
- [`references/real-estate.md`](references/real-estate.md) — Zillow / Redfin filters and bracketed params
|
|
156
|
+
- [`references/travel.md`](references/travel.md) — Airbnb / Booking / Google Flights (lodging + transport)
|
|
157
|
+
- [`references/ecommerce.md`](references/ecommerce.md) — Amazon / Shopify
|
|
158
|
+
- [`references/local-business.md`](references/local-business.md) — Maps (search/place/reviews/photos/posts) / Yelp / YellowPages
|
|
159
|
+
- [`references/jobs.md`](references/jobs.md) — Indeed / Glassdoor
|
|
160
|
+
- [`references/youtube.md`](references/youtube.md) — search / video / channel / transcript
|
|
161
|
+
- [`references/all-commands.md`](references/all-commands.md) — full subcommand index with credit costs
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
## Limitations
|
|
165
|
+
|
|
166
|
+
* Requires access to HasData services and valid credentials.
|
|
167
|
+
* Data quality and available fields depend on the target website and extraction method used.
|
|
168
|
+
* Website changes can impact extraction results and may require adjustments to extraction logic.
|
|
169
|
+
* Rate limits, quotas, and account restrictions may apply depending on the endpoint and subscription plan.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# All commands
|
|
2
|
+
|
|
3
|
+
Authoritative source: `hasdata --help`. This file is a snapshot — when in doubt, run `hasdata <api> --help` directly.
|
|
4
|
+
|
|
5
|
+
## Search
|
|
6
|
+
|
|
7
|
+
| Command | Cost | Notes |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| `google-serp` | 10 | Full Google SERP — organic, ads, knowledge graph, PAA, AI overview |
|
|
10
|
+
| `google-serp-light` | 5 | Cheap single-page SERP |
|
|
11
|
+
| `google-ai-mode` | 5 | Google AI Mode answer |
|
|
12
|
+
| `google-news` | 10 | Google News results |
|
|
13
|
+
| `google-shopping` | 10 | Google Shopping results |
|
|
14
|
+
| `google-immersive-product` | 5 | Immersive product page details |
|
|
15
|
+
| `google-events` | 5 | Google Events |
|
|
16
|
+
| `google-short-videos` | 10 | Short videos panel |
|
|
17
|
+
| `google-trends` | 5 | Search trends data |
|
|
18
|
+
| `google-images` | 5 | Image search |
|
|
19
|
+
| `bing-serp` | 10 | Bing SERP |
|
|
20
|
+
|
|
21
|
+
## Maps & local
|
|
22
|
+
|
|
23
|
+
| Command | Cost | Notes |
|
|
24
|
+
| --- | --- | --- |
|
|
25
|
+
| `google-maps` | 5 | Maps search |
|
|
26
|
+
| `google-maps-place` | 5 | Single place by place_id |
|
|
27
|
+
| `google-maps-reviews` | 5 | Place reviews |
|
|
28
|
+
| `google-maps-contributor-reviews` | 5 | Reviews by contributor |
|
|
29
|
+
| `google-maps-photos` | 5 | Place photos |
|
|
30
|
+
| `google-maps-posts` | 10 | Business-owner posts (offers, events, announcements) |
|
|
31
|
+
| `yelp-search` | 5 | Yelp business search |
|
|
32
|
+
| `yelp-place` | 5 | Single Yelp business |
|
|
33
|
+
| `yellowpages-search` | 5 | YellowPages search |
|
|
34
|
+
| `yellowpages-place` | 5 | Single YellowPages listing |
|
|
35
|
+
|
|
36
|
+
## E-commerce
|
|
37
|
+
|
|
38
|
+
| Command | Cost | Notes |
|
|
39
|
+
| --- | --- | --- |
|
|
40
|
+
| `amazon-search` | 5 | Amazon search results |
|
|
41
|
+
| `amazon-product` | 5 | Amazon product by ASIN |
|
|
42
|
+
| `amazon-seller` | 5 | Amazon seller profile |
|
|
43
|
+
| `amazon-seller-products` | 5 | Seller's product catalog |
|
|
44
|
+
| `shopify-products` | 5 | Any Shopify store's products |
|
|
45
|
+
| `shopify-collections` | 5 | Shopify collections |
|
|
46
|
+
|
|
47
|
+
## Real estate
|
|
48
|
+
|
|
49
|
+
| Command | Cost | Notes |
|
|
50
|
+
| --- | --- | --- |
|
|
51
|
+
| `zillow-listing` | 5 | Zillow filtered search |
|
|
52
|
+
| `zillow-property` | 5 | Zillow single property |
|
|
53
|
+
| `redfin-listing` | 5 | Redfin filtered search |
|
|
54
|
+
| `redfin-property` | 5 | Redfin single property |
|
|
55
|
+
|
|
56
|
+
## Travel
|
|
57
|
+
|
|
58
|
+
| Command | Cost | Notes |
|
|
59
|
+
| --- | --- | --- |
|
|
60
|
+
| `airbnb-listing` | 5 | Airbnb filtered search |
|
|
61
|
+
| `airbnb-property` | 5 | Airbnb single listing |
|
|
62
|
+
| `booking-search` | 10 | Booking.com search (hotels, apartments) |
|
|
63
|
+
| `booking-place` | 10 | Booking.com property + room/rate list |
|
|
64
|
+
| `google-flights` | 15 | Flight search via Google Flights |
|
|
65
|
+
|
|
66
|
+
## Jobs
|
|
67
|
+
|
|
68
|
+
| Command | Cost | Notes |
|
|
69
|
+
| --- | --- | --- |
|
|
70
|
+
| `indeed-listing` | 5 | Indeed search |
|
|
71
|
+
| `indeed-job` | 5 | Single Indeed posting |
|
|
72
|
+
| `glassdoor-listing` | 10 | Glassdoor search (with ratings) |
|
|
73
|
+
| `glassdoor-job` | 10 | Single Glassdoor posting |
|
|
74
|
+
|
|
75
|
+
## Web
|
|
76
|
+
|
|
77
|
+
| Command | Cost | Notes |
|
|
78
|
+
| --- | --- | --- |
|
|
79
|
+
| `web-scraping` | 10 | Arbitrary URL — JS rendering, AI extraction, markdown output, screenshots |
|
|
80
|
+
|
|
81
|
+
## Social
|
|
82
|
+
|
|
83
|
+
| Command | Cost | Notes |
|
|
84
|
+
| --- | --- | --- |
|
|
85
|
+
| `instagram-profile` | 5 | Instagram profile by handle |
|
|
86
|
+
|
|
87
|
+
## YouTube
|
|
88
|
+
|
|
89
|
+
| Command | Cost | Notes |
|
|
90
|
+
| --- | --- | --- |
|
|
91
|
+
| `youtube-search-api` | 10 | YouTube search (videos, shorts, channels, playlists) |
|
|
92
|
+
| `youtube-video-api` | 10 | Single video metadata + stats + related |
|
|
93
|
+
| `youtube-channel-api` | 10 | Channel home / videos / shorts / playlists / community |
|
|
94
|
+
| `youtube-transcript-api` | 10 | Full transcript with millisecond offsets |
|
|
95
|
+
|
|
96
|
+
## Utility (no cost)
|
|
97
|
+
|
|
98
|
+
| Command | Notes |
|
|
99
|
+
| --- | --- |
|
|
100
|
+
| `configure` | Interactive setup; writes ~/.hasdata/config.yaml |
|
|
101
|
+
| `version` | Print version |
|
|
102
|
+
| `update` | Self-update from GitHub Releases |
|
|
103
|
+
| `completion {bash\|zsh\|fish\|powershell}` | Generate shell completion |
|
|
104
|
+
|
|
105
|
+
## Deprecated
|
|
106
|
+
|
|
107
|
+
`amazon-reviews` is deprecated — Amazon now requires login to access reviews. The subcommand still exists for backwards compatibility but currently returns no data; don't suggest it.
|