scavio 0.12.0 → 0.14.0

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/README.md CHANGED
@@ -33,16 +33,31 @@ const client = new Scavio({
33
33
  baseUrl: "https://api.scavio.dev", // default
34
34
  timeout: 30_000, // ms, default
35
35
  maxRequestsPerSecond: 1, // 1-10, default 1
36
+ maxRetries: 2, // default 2, set 0 to disable
36
37
  });
37
38
  ```
38
39
 
40
+ `maxRetries` is the number of extra attempts after the first request, applied
41
+ only to transient failures — HTTP 429, 500, 502, 503, 504 and network or timeout
42
+ errors. Backoff is exponential with full jitter, capped at 8s, and a
43
+ `Retry-After` header is honored when the API sends one. Non-transient errors
44
+ (400, 401, 402, 404) are never retried.
45
+
46
+ `maxRequestsPerSecond` throttles the client so it never sends more than N
47
+ requests in any one-second window. Your plan also has a server-side concurrency
48
+ limit on simultaneous in-flight requests: 1 on free and pay-as-you-go, 2 on
49
+ Project, 3 on Bootstrap, 5 on Startup, 10 on Growth.
50
+
39
51
  ## API Reference
40
52
 
41
53
  ### Google
42
54
 
43
- Every method hits `/api/v2/google` and returns Google's full response (raw
44
- passthrough); each costs 1 credit. Any scrape.do parameter can be passed
45
- through.
55
+ Each method hits its own `/api/v2/google*` endpoint and returns Google's full
56
+ response (raw passthrough); each costs 1 credit. Results come back as
57
+ `organic_results[]` with `link` and `snippet`. Geo and paging use `gl`, `hl`,
58
+ `start`, `google_domain` and `device` — the old v1 vocabulary (`light_request`,
59
+ `country_code`, `language`, `search_type`, `page`) does not exist on v2 and is
60
+ dropped server-side.
46
61
 
47
62
  ```typescript
48
63
  // SERP search (includes the AI Overview when Google shows one)
@@ -129,6 +144,9 @@ await client.walmart.product({
129
144
 
130
145
  ### YouTube
131
146
 
147
+ Credit cost varies by endpoint: `transcript` costs 8; `streams` costs 3;
148
+ `search` and `shorts` cost 2; every other YouTube endpoint costs 1.
149
+
132
150
  ```typescript
133
151
  // Search videos
134
152
  await client.youtube.search({
@@ -176,6 +194,14 @@ await client.youtube.channelResolve({ channel: "@mkbhd" }); // handle/URL -> id
176
194
 
177
195
  ### Reddit
178
196
 
197
+ Every Reddit endpoint costs 1 credit.
198
+
199
+ `search()` takes only `query` and `cursor` — there is no result-type or sort
200
+ filter upstream, so anything else is dropped server-side. It returns
201
+ `data.results` with `next_cursor` and `has_more`. `post()` returns a flat post
202
+ object under `data` and carries no comments; use `postComments()` for those.
203
+ The subreddit and user feeds return `data.posts`.
204
+
179
205
  ```typescript
180
206
  // Search posts
181
207
  await client.reddit.search({ query: "typescript", cursor: "..." });
@@ -253,16 +279,20 @@ await client.linkedin.post({ post_id: "7488618410256523265" });
253
279
  await client.linkedin.postComments({ post_id: "7488618410256523265", page: 1 });
254
280
  ```
255
281
 
256
- All LinkedIn endpoints cost 1 credit.
282
+ Credit cost varies by endpoint: `job` costs 30; `personPosts`, `companyPosts`,
283
+ `searchJobs` and `postComments` cost 10 per page; `person`, `personAbout`,
284
+ `company` and `post` cost 1.
257
285
 
258
286
  > **Retired endpoints.** The upstream provider withdrew the datasets behind
259
287
  > `personContact`, `companyPeople`, `companyJobs`, `searchPeople` and
260
288
  > `searchPosts`. They remain callable but always return HTTP 410 and are never
261
289
  > billed. `company()` returns `featured_employees` (a small sample of staff), and
262
290
  > `searchJobs()` with a company name substitutes for `companyJobs()`.
263
- >
264
- > `personPosts` and `companyPosts` return up to 50 posts; the provider exposes no
265
- > further pages, so those endpoints no longer take a cursor.
291
+
292
+ `personPosts`, `companyPosts` and `searchJobs` paginate: pass the previous
293
+ response's `next_cursor` as `cursor` to fetch the next page. `personPosts` also
294
+ takes `type` (`"posts"`, `"comments"` or `"reactions"`) to pick the feed.
295
+ `postComments` pages with a 1-based `page` instead.
266
296
 
267
297
  ### TikTok
268
298
 
@@ -282,8 +312,8 @@ await client.tiktok.videoComments({ video_id: "vid123", count: 20 });
282
312
  // Comment replies
283
313
  await client.tiktok.commentReplies({ video_id: "vid123", comment_id: "c456" });
284
314
 
285
- // Search videos
286
- await client.tiktok.searchVideos({ keyword: "dance", sort_type: "likes" });
315
+ // Search videos (sort_type: '0' = relevance, '1' = most likes)
316
+ await client.tiktok.searchVideos({ keyword: "dance", sort_type: "1" });
287
317
 
288
318
  // Search users
289
319
  await client.tiktok.searchUsers({ keyword: "cooking" });
@@ -362,8 +392,16 @@ await client.tiktokShop.resolve({ url: "https://vt.tiktok.com/ZT2AHoGsE/" });
362
392
 
363
393
  ### Instagram
364
394
 
365
- Credit cost varies by endpoint: `userPosts` costs 2 credits, every other
366
- Instagram endpoint costs 8.
395
+ Credit cost varies by endpoint, in three tiers:
396
+
397
+ | Credits | Methods |
398
+ |---|---|
399
+ | 2 | `userPosts` |
400
+ | 8 | `post`, `commentReplies` |
401
+ | 10 | `profile`, `userReels`, `userTagged`, `userStories`, `postComments`, `searchUsers`, `searchHashtags`, `userFollowers`, `userFollowings` |
402
+
403
+ The 10-credit endpoints run two upstream providers in parallel and bill both
404
+ legs; the 8-credit ones have no fallback leg to hedge against.
367
405
 
368
406
  ```typescript
369
407
  // User profile
@@ -420,12 +458,19 @@ All error classes:
420
458
  | Class | HTTP Status | Description |
421
459
  |-------|------------|-------------|
422
460
  | `MissingAPIKeyError` | — | No API key provided |
461
+ | `ScavioConnectionError` | — | Request never reached the API (DNS, reset, TLS) |
462
+ | `ScavioTimeoutError` | — | Request exceeded the configured `timeout` |
463
+ | `BadRequestError` | 400 | Invalid request parameters |
423
464
  | `InvalidAPIKeyError` | 401 | Invalid API key |
424
465
  | `InsufficientCreditsError` | 402 | No credits remaining |
425
- | `BadRequestError` | 400 | Invalid request parameters |
466
+ | `NotFoundError` | 404 | No data upstream for that id (see TikTok Shop above) |
426
467
  | `RateLimitError` | 429 | Rate limit exceeded |
427
468
  | `ScavioAPIError` | other | Catch-all (has `.statusCode`) |
428
469
 
470
+ Every class extends `ScavioError`, so `catch (e) { if (e instanceof ScavioError) }`
471
+ matches all of them. All except `MissingAPIKeyError`, `ScavioConnectionError` and
472
+ `ScavioTimeoutError` carry `.statusCode` and `.responseBody`.
473
+
429
474
  ## Runtime Support
430
475
 
431
476
  - Node.js 18+
package/dist/index.cjs CHANGED
@@ -398,12 +398,17 @@ var RedditNamespace = class {
398
398
  this.client = client;
399
399
  }
400
400
  client;
401
+ /** Returns `data.results` plus `next_cursor` / `has_more` (not `data.posts`). */
401
402
  async search(options) {
402
403
  return this.client._post("/api/v1/reddit/search", options);
403
404
  }
404
405
  async searchSuggestions(options) {
405
406
  return this.client._post("/api/v1/reddit/search/suggestions", options);
406
407
  }
408
+ /**
409
+ * Returns a flat post object under `data` (post_id, title, text, url,
410
+ * subreddit, author, score, ...). Comments are a separate call.
411
+ */
407
412
  async post(options) {
408
413
  return this.client._post("/api/v1/reddit/post", options);
409
414
  }