scrapebadger 0.3.1 → 0.7.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/dist/index.js CHANGED
@@ -710,6 +710,59 @@ var TweetsClient = class {
710
710
  };
711
711
  yield* paginate(fetchPage, options);
712
712
  }
713
+ /**
714
+ * Get the edit history of a tweet.
715
+ *
716
+ * @param tweetId - The tweet ID to get edit history for.
717
+ * @returns Paginated response containing tweet versions.
718
+ *
719
+ * @example
720
+ * ```typescript
721
+ * const history = await client.twitter.tweets.getEditHistory("1234567890");
722
+ * console.log(`${history.data.length} version(s) of this tweet`);
723
+ * ```
724
+ */
725
+ async getEditHistory(tweetId) {
726
+ const response = await this.client.request(
727
+ `/v1/twitter/tweets/tweet/${tweetId}/edit_history`
728
+ );
729
+ return createPaginatedResponse(response.data ?? [], void 0);
730
+ }
731
+ /**
732
+ * Get community notes (Birdwatch) attached to a tweet.
733
+ *
734
+ * @param tweetId - The tweet ID to get community notes for.
735
+ * @returns Paginated response containing community notes.
736
+ *
737
+ * @example
738
+ * ```typescript
739
+ * const notes = await client.twitter.tweets.getCommunityNotes("1234567890");
740
+ * for (const note of notes.data) {
741
+ * console.log(note.text);
742
+ * }
743
+ * ```
744
+ */
745
+ async getCommunityNotes(tweetId) {
746
+ const response = await this.client.request(
747
+ `/v1/twitter/tweets/tweet/${tweetId}/community_notes`
748
+ );
749
+ return createPaginatedResponse(response.data ?? [], void 0);
750
+ }
751
+ /**
752
+ * Get a long-form article by its ID.
753
+ *
754
+ * @param articleId - The article ID to fetch.
755
+ * @returns The article data.
756
+ *
757
+ * @example
758
+ * ```typescript
759
+ * const article = await client.twitter.tweets.getArticle("abc123");
760
+ * console.log(`${article.title}: ${article.text?.slice(0, 100)}...`);
761
+ * ```
762
+ */
763
+ async getArticle(articleId) {
764
+ return this.client.request(`/v1/twitter/tweets/article/${articleId}`);
765
+ }
713
766
  };
714
767
 
715
768
  // src/twitter/users.ts
@@ -1021,6 +1074,92 @@ var UsersClient = class {
1021
1074
  };
1022
1075
  yield* paginate(fetchPage, options);
1023
1076
  }
1077
+ /**
1078
+ * Get multiple users by their numeric IDs in a single request.
1079
+ *
1080
+ * @param userIds - List of user IDs to fetch.
1081
+ * @returns Paginated response containing the matching users.
1082
+ *
1083
+ * @example
1084
+ * ```typescript
1085
+ * const users = await client.twitter.users.getByIds(["44196397", "783214"]);
1086
+ * for (const user of users.data) {
1087
+ * console.log(`@${user.username}`);
1088
+ * }
1089
+ * ```
1090
+ */
1091
+ async getByIds(userIds) {
1092
+ const response = await this.client.request(
1093
+ "/v1/twitter/users/batch_by_ids",
1094
+ { params: { user_ids: userIds.join(",") } }
1095
+ );
1096
+ return createPaginatedResponse(response.data ?? [], void 0);
1097
+ }
1098
+ /**
1099
+ * Get multiple users by their usernames in a single request.
1100
+ *
1101
+ * @param usernames - List of usernames (without @) to fetch.
1102
+ * @returns Paginated response containing the matching users.
1103
+ *
1104
+ * @example
1105
+ * ```typescript
1106
+ * const users = await client.twitter.users.getByUsernames(["elonmusk", "twitter"]);
1107
+ * for (const user of users.data) {
1108
+ * console.log(`${user.name}: ${user.followers_count?.toLocaleString()} followers`);
1109
+ * }
1110
+ * ```
1111
+ */
1112
+ async getByUsernames(usernames) {
1113
+ const response = await this.client.request(
1114
+ "/v1/twitter/users/batch_by_usernames",
1115
+ { params: { usernames: usernames.join(",") } }
1116
+ );
1117
+ return createPaginatedResponse(response.data ?? [], void 0);
1118
+ }
1119
+ /**
1120
+ * Get tweets that mention a user.
1121
+ *
1122
+ * @param username - The user's username (without @).
1123
+ * @param options - Pagination options with optional count.
1124
+ * @returns Paginated response containing tweets mentioning the user.
1125
+ *
1126
+ * @example
1127
+ * ```typescript
1128
+ * const mentions = await client.twitter.users.getMentions("elonmusk");
1129
+ * for (const tweet of mentions.data) {
1130
+ * console.log(`@${tweet.username}: ${tweet.text.slice(0, 100)}...`);
1131
+ * }
1132
+ * ```
1133
+ */
1134
+ async getMentions(username, options = {}) {
1135
+ const response = await this.client.request(
1136
+ `/v1/twitter/users/${username}/mentions`,
1137
+ { params: { count: options.count, cursor: options.cursor } }
1138
+ );
1139
+ return createPaginatedResponse(response.data ?? [], response.next_cursor);
1140
+ }
1141
+ /**
1142
+ * Get long-form articles authored by a user.
1143
+ *
1144
+ * @param userId - The user's numeric ID.
1145
+ * @param options - Pagination options with optional count.
1146
+ * @returns Paginated response containing the user's articles as tweets.
1147
+ *
1148
+ * @example
1149
+ * ```typescript
1150
+ * const articles = await client.twitter.users.getArticles("44196397");
1151
+ * for (const article of articles.data) {
1152
+ * console.log(article.text?.slice(0, 100));
1153
+ * }
1154
+ * ```
1155
+ */
1156
+ async getArticles(userId, options = {}) {
1157
+ const response = await this.client.request(
1158
+ `/v1/twitter/users/${userId}/articles`,
1159
+ { params: { count: options.count, cursor: options.cursor } }
1160
+ );
1161
+ return createPaginatedResponse(response.data ?? [], response.next_cursor);
1162
+ }
1024
1163
  };
1025
1164
 
1026
1165
  // src/twitter/lists.ts
@@ -1167,6 +1306,29 @@ var ListsClient = class {
1167
1306
  );
1168
1307
  return createPaginatedResponse(response.data ?? [], response.next_cursor);
1169
1308
  }
1309
+ /**
1310
+ * Search tweets within a specific list.
1311
+ *
1312
+ * @param listId - The list ID to search within.
1313
+ * @param query - Search query string.
1314
+ * @param options - Pagination options with optional count.
1315
+ * @returns Paginated response containing matching tweets from the list.
1316
+ *
1317
+ * @example
1318
+ * ```typescript
1319
+ * const results = await client.twitter.lists.searchTweets("123456", "python");
1320
+ * for (const tweet of results.data) {
1321
+ * console.log(`@${tweet.username}: ${tweet.text.slice(0, 100)}...`);
1322
+ * }
1323
+ * ```
1324
+ */
1325
+ async searchTweets(listId, query, options = {}) {
1326
+ const response = await this.client.request(
1327
+ `/v1/twitter/lists/${listId}/search_tweets`,
1328
+ { params: { query, count: options.count, cursor: options.cursor } }
1329
+ );
1330
+ return createPaginatedResponse(response.data ?? [], response.next_cursor);
1331
+ }
1170
1332
  };
1171
1333
 
1172
1334
  // src/twitter/communities.ts
@@ -2030,7 +2192,7 @@ var StreamClient = class {
2030
2192
  return;
2031
2193
  }
2032
2194
  if (!reconnect) {
2033
- const reasonStr = reason instanceof Buffer ? reason.toString() : String(reason ?? "");
2195
+ const reasonStr = reason instanceof Buffer ? reason.toString() : typeof reason === "string" ? reason : "";
2034
2196
  emitter.emit(
2035
2197
  "error",
2036
2198
  new WebSocketStreamError(`WebSocket closed: ${reasonStr || String(code)}`)
@@ -2188,6 +2350,46 @@ function verifyWebhookSignature(secret, body, signatureHeader) {
2188
2350
  }
2189
2351
  }
2190
2352
 
2353
+ // src/twitter/spaces.ts
2354
+ var SpacesClient = class {
2355
+ client;
2356
+ constructor(client) {
2357
+ this.client = client;
2358
+ }
2359
+ /**
2360
+ * Get details for a specific Twitter Space.
2361
+ *
2362
+ * @param spaceId - The Space ID to fetch.
2363
+ * @returns The Space data.
2364
+ * @throws NotFoundError - If the Space doesn't exist.
2365
+ *
2366
+ * @example
2367
+ * ```typescript
2368
+ * const space = await client.twitter.spaces.getDetail("1eaKbrPPbPwKX");
2369
+ * console.log(`${space.title} — ${space.participant_count} participants`);
2370
+ * ```
2371
+ */
2372
+ async getDetail(spaceId) {
2373
+ return this.client.request(`/v1/twitter/spaces/${spaceId}`);
2374
+ }
2375
+ /**
2376
+ * Get details for a live video broadcast.
2377
+ *
2378
+ * @param broadcastId - The broadcast ID to fetch.
2379
+ * @returns The broadcast data.
2380
+ * @throws NotFoundError - If the broadcast doesn't exist.
2381
+ *
2382
+ * @example
2383
+ * ```typescript
2384
+ * const broadcast = await client.twitter.spaces.getBroadcast("broadcast123");
2385
+ * console.log(`${broadcast.title}: ${broadcast.total_viewers} viewers`);
2386
+ * ```
2387
+ */
2388
+ async getBroadcast(broadcastId) {
2389
+ return this.client.request(`/v1/twitter/spaces/broadcast/${broadcastId}`);
2390
+ }
2391
+ };
2392
+
2191
2393
  // src/twitter/client.ts
2192
2394
  var TwitterClient = class {
2193
2395
  /** Client for tweet operations */
@@ -2204,6 +2406,8 @@ var TwitterClient = class {
2204
2406
  geo;
2205
2407
  /** Client for real-time stream monitor management and WebSocket streaming */
2206
2408
  stream;
2409
+ /** Client for Twitter Spaces and live broadcast operations */
2410
+ spaces;
2207
2411
  /**
2208
2412
  * Create a new Twitter client.
2209
2413
  *
@@ -2217,6 +2421,7 @@ var TwitterClient = class {
2217
2421
  this.trends = new TrendsClient(client);
2218
2422
  this.geo = new GeoClient(client);
2219
2423
  this.stream = new StreamClient(client);
2424
+ this.spaces = new SpacesClient(client);
2220
2425
  }
2221
2426
  };
2222
2427
 
@@ -2228,94 +2433,845 @@ var WebClient = class {
2228
2433
  }
2229
2434
  /**
2230
2435
  * Scrape a web page.
2436
+ *
2437
+ * @param url - The URL to scrape
2438
+ * @param options - Scrape configuration options
2439
+ * @returns The scrape result including content, metadata, and credit usage
2231
2440
  */
2232
2441
  async scrape(url, options = {}) {
2233
2442
  const body = { url };
2234
- if (options.renderJs) body.render_js = true;
2235
- if (options.outputFormat && options.outputFormat !== "html")
2236
- body.output_format = options.outputFormat;
2237
- if (options.proxyCountry) body.proxy_country = options.proxyCountry;
2238
- if (options.proxyType) body.proxy_type = options.proxyType;
2239
- if (options.sessionId) body.session_id = options.sessionId;
2240
- if (options.engine) body.engine = options.engine;
2443
+ if (options.format !== void 0) body.format = options.format;
2444
+ if (options.renderJs !== void 0) body.render_js = options.renderJs;
2445
+ if (options.engine !== void 0) body.engine = options.engine;
2446
+ if (options.waitFor !== void 0) body.wait_for = options.waitFor;
2447
+ if (options.waitTimeout !== void 0) body.wait_timeout = options.waitTimeout;
2448
+ if (options.waitAfterLoad !== void 0) body.wait_after_load = options.waitAfterLoad;
2449
+ if (options.jsScenario !== void 0) body.js_scenario = options.jsScenario;
2450
+ if (options.sessionId !== void 0) body.session_id = options.sessionId;
2451
+ if (options.retryCount !== void 0) body.retry_count = options.retryCount;
2452
+ if (options.retryOnBlock !== void 0) body.retry_on_block = options.retryOnBlock;
2453
+ if (options.country !== void 0) body.country = options.country;
2454
+ if (options.customHeaders !== void 0) body.custom_headers = options.customHeaders;
2455
+ if (options.screenshot !== void 0) body.screenshot = options.screenshot;
2456
+ if (options.video !== void 0) body.video = options.video;
2457
+ if (options.antiBot !== void 0) body.anti_bot = options.antiBot;
2458
+ if (options.escalate !== void 0) body.escalate = options.escalate;
2241
2459
  if (options.maxCost !== void 0) body.max_cost = options.maxCost;
2242
- if (options.headers) body.headers = options.headers;
2243
- if (options.waitFor) body.wait_for = options.waitFor;
2244
- if (options.timeout !== void 0) body.timeout = options.timeout;
2245
- if (options.jsScenario) body.js_scenario = options.jsScenario;
2460
+ if (options.aiExtract !== void 0) body.ai_extract = options.aiExtract;
2461
+ if (options.aiPrompt !== void 0) body.ai_prompt = options.aiPrompt;
2462
+ if (options.rawContent !== void 0) body.raw_content = options.rawContent;
2463
+ if (options.skipBotDetection !== void 0) body.skip_bot_detection = options.skipBotDetection;
2246
2464
  return this.client.request("/v1/web/scrape", {
2247
2465
  method: "POST",
2248
2466
  body
2249
2467
  });
2250
2468
  }
2251
2469
  /**
2252
- * Take a screenshot of a web page.
2470
+ * Extract structured data from a web page using AI.
2471
+ *
2472
+ * Convenience wrapper around {@link scrape} that enables AI extraction
2473
+ * with the given prompt and defaults to markdown format.
2474
+ *
2475
+ * @param url - The URL to extract data from
2476
+ * @param prompt - Natural language prompt describing what to extract (max 2000 chars)
2477
+ * @param options - Additional scrape options (aiExtract and aiPrompt are set automatically)
2478
+ * @returns The scrape result with ai_extraction populated
2253
2479
  */
2254
- async screenshot(url, options = {}) {
2255
- const body = { url };
2256
- if (options.fullPage) body.full_page = true;
2257
- if (options.viewportWidth && options.viewportWidth !== 1280)
2258
- body.viewport_width = options.viewportWidth;
2259
- if (options.viewportHeight && options.viewportHeight !== 720)
2260
- body.viewport_height = options.viewportHeight;
2261
- if (options.imageFormat && options.imageFormat !== "png")
2262
- body.image_format = options.imageFormat;
2263
- if (options.waitFor) body.wait_for = options.waitFor;
2264
- if (options.timeout !== void 0) body.timeout = options.timeout;
2265
- return this.client.request("/v1/web/screenshot", {
2266
- method: "POST",
2267
- body
2480
+ async extract(url, prompt, options = {}) {
2481
+ return this.scrape(url, {
2482
+ format: "markdown",
2483
+ ...options,
2484
+ aiExtract: true,
2485
+ aiPrompt: prompt
2268
2486
  });
2269
2487
  }
2270
2488
  /**
2271
- * Extract structured data from a web page.
2489
+ * Detect anti-bot systems on a URL.
2490
+ *
2491
+ * @param url - The URL to analyze
2492
+ * @param options - Detection options
2493
+ * @returns Detection results including identified anti-bot and captcha systems
2272
2494
  */
2273
- async extract(url, options = {}) {
2495
+ async detect(url, options = {}) {
2274
2496
  const body = { url };
2275
- if (options.schema) body.extraction_schema = options.schema;
2276
- if (options.renderJs) body.render_js = true;
2277
- if (options.waitFor) body.wait_for = options.waitFor;
2278
2497
  if (options.timeout !== void 0) body.timeout = options.timeout;
2279
- return this.client.request("/v1/web/extract", {
2498
+ if (options.country !== void 0) body.country = options.country;
2499
+ return this.client.request("/v1/web/detect", {
2280
2500
  method: "POST",
2281
2501
  body
2282
2502
  });
2283
2503
  }
2504
+ };
2505
+
2506
+ // src/vinted/search.ts
2507
+ var SearchClient = class {
2508
+ client;
2509
+ constructor(client) {
2510
+ this.client = client;
2511
+ }
2284
2512
  /**
2285
- * Scrape multiple URLs in a batch.
2513
+ * Search for Vinted items.
2514
+ *
2515
+ * @param params - Search parameters including query, filters, and pagination.
2516
+ * @returns Search results with items and pagination metadata.
2517
+ * @throws AuthenticationError - If the API key is invalid.
2518
+ * @throws ValidationError - If the search parameters are invalid.
2519
+ *
2520
+ * @example
2521
+ * ```typescript
2522
+ * const results = await client.vinted.search.search({
2523
+ * query: "vintage jacket",
2524
+ * market: "fr",
2525
+ * page: 1,
2526
+ * per_page: 20,
2527
+ * order: "newest_first",
2528
+ * });
2529
+ * console.log(`Found ${results.pagination.total_entries} items`);
2530
+ * ```
2286
2531
  */
2287
- async batch(urls, options = {}) {
2288
- const body = { urls };
2289
- if (options.renderJs) body.render_js = true;
2290
- if (options.outputFormat && options.outputFormat !== "html")
2291
- body.output_format = options.outputFormat;
2292
- if (options.maxConcurrency && options.maxConcurrency !== 5)
2293
- body.max_concurrency = options.maxConcurrency;
2294
- if (options.engine) body.engine = options.engine;
2295
- if (options.timeout !== void 0) body.timeout = options.timeout;
2296
- return this.client.request("/v1/web/batch", {
2297
- method: "POST",
2298
- body
2532
+ async search(params) {
2533
+ return this.client.request("/v1/vinted/search", {
2534
+ params: {
2535
+ query: params.query,
2536
+ market: params.market,
2537
+ page: params.page,
2538
+ per_page: params.per_page,
2539
+ price_from: params.price_from,
2540
+ price_to: params.price_to,
2541
+ brand_ids: params.brand_ids,
2542
+ color_ids: params.color_ids,
2543
+ status_ids: params.status_ids,
2544
+ order: params.order
2545
+ }
2299
2546
  });
2300
2547
  }
2548
+ };
2549
+
2550
+ // src/vinted/items.ts
2551
+ var ItemsClient = class {
2552
+ client;
2553
+ constructor(client) {
2554
+ this.client = client;
2555
+ }
2301
2556
  /**
2302
- * Create a new scraping session for a domain.
2557
+ * Get a single item by ID.
2558
+ *
2559
+ * @param itemId - The Vinted item ID to fetch.
2560
+ * @param options - Optional parameters.
2561
+ * @param options.market - Market code (default: "fr").
2562
+ * @returns The item detail response including full item data.
2563
+ * @throws NotFoundError - If the item doesn't exist.
2564
+ * @throws AuthenticationError - If the API key is invalid.
2565
+ *
2566
+ * @example
2567
+ * ```typescript
2568
+ * const response = await client.vinted.items.get(123456789);
2569
+ * const { item } = response;
2570
+ * console.log(`${item.title}: ${item.description}`);
2571
+ * console.log(`Brand: ${item.brand_title}, Size: ${item.size_title}`);
2572
+ * console.log(`Photos: ${item.photos.length}`);
2573
+ * ```
2303
2574
  */
2304
- async createSession(domain, persist = true) {
2305
- return this.client.request("/v1/web/sessions", {
2306
- method: "POST",
2307
- body: {
2308
- domain,
2309
- new_session: true,
2310
- persist_session: persist
2575
+ async get(itemId, options = {}) {
2576
+ return this.client.request(
2577
+ `/v1/vinted/items/${itemId}`,
2578
+ { params: { market: options.market } }
2579
+ );
2580
+ }
2581
+ };
2582
+
2583
+ // src/vinted/users.ts
2584
+ var UsersClient2 = class {
2585
+ client;
2586
+ constructor(client) {
2587
+ this.client = client;
2588
+ }
2589
+ /**
2590
+ * Get a user's profile.
2591
+ *
2592
+ * @param userId - The Vinted user ID.
2593
+ * @param options - Optional parameters.
2594
+ * @param options.market - Market code (default: "fr").
2595
+ * @returns The user profile response.
2596
+ * @throws NotFoundError - If the user doesn't exist.
2597
+ * @throws AuthenticationError - If the API key is invalid.
2598
+ *
2599
+ * @example
2600
+ * ```typescript
2601
+ * const response = await client.vinted.users.getProfile(12345);
2602
+ * const { user } = response;
2603
+ * console.log(`${user.login} from ${user.city}, ${user.country_code}`);
2604
+ * console.log(`Reputation: ${user.feedback_reputation}`);
2605
+ * console.log(`Items: ${user.item_count}, Followers: ${user.followers_count}`);
2606
+ * ```
2607
+ */
2608
+ async getProfile(userId, options = {}) {
2609
+ return this.client.request(
2610
+ `/v1/vinted/users/${userId}`,
2611
+ { params: { market: options.market } }
2612
+ );
2613
+ }
2614
+ /**
2615
+ * Get items listed by a user.
2616
+ *
2617
+ * @param userId - The Vinted user ID.
2618
+ * @param options - Optional parameters for pagination and market.
2619
+ * @param options.market - Market code (default: "fr").
2620
+ * @param options.page - Page number.
2621
+ * @param options.per_page - Items per page.
2622
+ * @returns The user's items with pagination metadata.
2623
+ * @throws NotFoundError - If the user doesn't exist.
2624
+ * @throws AuthenticationError - If the API key is invalid.
2625
+ *
2626
+ * @example
2627
+ * ```typescript
2628
+ * const response = await client.vinted.users.getItems(12345, {
2629
+ * market: "de",
2630
+ * page: 1,
2631
+ * per_page: 20,
2632
+ * });
2633
+ * console.log(`Page ${response.pagination.current_page} of ${response.pagination.total_pages}`);
2634
+ * for (const item of response.items) {
2635
+ * console.log(`${item.title} — ${item.price.amount} ${item.price.currency_code}`);
2636
+ * }
2637
+ * ```
2638
+ */
2639
+ async getItems(userId, options = {}) {
2640
+ return this.client.request(
2641
+ `/v1/vinted/users/${userId}/items`,
2642
+ {
2643
+ params: {
2644
+ market: options.market,
2645
+ page: options.page,
2646
+ per_page: options.per_page
2647
+ }
2311
2648
  }
2649
+ );
2650
+ }
2651
+ };
2652
+
2653
+ // src/vinted/reference.ts
2654
+ var ReferenceClient = class {
2655
+ client;
2656
+ constructor(client) {
2657
+ this.client = client;
2658
+ }
2659
+ /**
2660
+ * Search for brands by keyword.
2661
+ *
2662
+ * @param options - Optional parameters.
2663
+ * @param options.keyword - Brand name to search for.
2664
+ * @param options.market - Market code (default: "fr").
2665
+ * @param options.per_page - Number of results per page.
2666
+ * @returns Brands matching the keyword.
2667
+ *
2668
+ * @example
2669
+ * ```typescript
2670
+ * const response = await client.vinted.reference.brands({
2671
+ * keyword: "adidas",
2672
+ * market: "de",
2673
+ * per_page: 10,
2674
+ * });
2675
+ * for (const brand of response.brands) {
2676
+ * console.log(`${brand.title} (${brand.slug}): ${brand.item_count} items`);
2677
+ * }
2678
+ * ```
2679
+ */
2680
+ async brands(options = {}) {
2681
+ return this.client.request("/v1/vinted/brands", {
2682
+ params: {
2683
+ keyword: options.keyword,
2684
+ market: options.market,
2685
+ per_page: options.per_page
2686
+ }
2687
+ });
2688
+ }
2689
+ /**
2690
+ * Get available colors for a market.
2691
+ *
2692
+ * @param options - Optional parameters.
2693
+ * @param options.market - Market code (default: "fr").
2694
+ * @returns List of available colors.
2695
+ *
2696
+ * @example
2697
+ * ```typescript
2698
+ * const response = await client.vinted.reference.colors({ market: "fr" });
2699
+ * for (const color of response.colors) {
2700
+ * console.log(`${color.title} (#${color.hex})`);
2701
+ * }
2702
+ * ```
2703
+ */
2704
+ async colors(options = {}) {
2705
+ return this.client.request("/v1/vinted/colors", {
2706
+ params: { market: options.market }
2707
+ });
2708
+ }
2709
+ /**
2710
+ * Get available item condition statuses for a market.
2711
+ *
2712
+ * @param options - Optional parameters.
2713
+ * @param options.market - Market code (default: "fr").
2714
+ * @returns List of item condition statuses.
2715
+ *
2716
+ * @example
2717
+ * ```typescript
2718
+ * const response = await client.vinted.reference.statuses({ market: "fr" });
2719
+ * for (const status of response.statuses) {
2720
+ * console.log(`${status.id}: ${status.title}`);
2721
+ * }
2722
+ * ```
2723
+ */
2724
+ async statuses(options = {}) {
2725
+ return this.client.request("/v1/vinted/statuses", {
2726
+ params: { market: options.market }
2727
+ });
2728
+ }
2729
+ /**
2730
+ * Get all available Vinted markets.
2731
+ *
2732
+ * @returns List of all supported Vinted markets/countries.
2733
+ *
2734
+ * @example
2735
+ * ```typescript
2736
+ * const response = await client.vinted.reference.markets();
2737
+ * for (const market of response.markets) {
2738
+ * console.log(`${market.name}: ${market.domain} (${market.currency})`);
2739
+ * }
2740
+ * ```
2741
+ */
2742
+ async markets() {
2743
+ return this.client.request("/v1/vinted/markets");
2744
+ }
2745
+ };
2746
+
2747
+ // src/vinted/client.ts
2748
+ var VintedClient = class {
2749
+ /** Client for item search operations */
2750
+ search;
2751
+ /** Client for individual item operations */
2752
+ items;
2753
+ /** Client for user operations */
2754
+ users;
2755
+ /** Client for reference data (brands, colors, statuses, markets) */
2756
+ reference;
2757
+ /**
2758
+ * Create a new Vinted client.
2759
+ *
2760
+ * @param client - The base HTTP client for making requests.
2761
+ */
2762
+ constructor(client) {
2763
+ this.search = new SearchClient(client);
2764
+ this.items = new ItemsClient(client);
2765
+ this.users = new UsersClient2(client);
2766
+ this.reference = new ReferenceClient(client);
2767
+ }
2768
+ };
2769
+
2770
+ // src/google/ai-mode.ts
2771
+ var AiModeClient = class {
2772
+ constructor(client) {
2773
+ this.client = client;
2774
+ }
2775
+ async search(params) {
2776
+ return this.client.request("/v1/google/ai-mode/search", {
2777
+ params: { ...params }
2778
+ });
2779
+ }
2780
+ };
2781
+
2782
+ // src/google/autocomplete.ts
2783
+ var AutocompleteClient = class {
2784
+ constructor(client) {
2785
+ this.client = client;
2786
+ }
2787
+ /**
2788
+ * Get Google autocomplete suggestions for a query.
2789
+ *
2790
+ * @example
2791
+ * ```typescript
2792
+ * const res = await client.google.autocomplete.get({ q: "apple" });
2793
+ * for (const s of res.suggestions) {
2794
+ * console.log(s.value, s.entity_name, s.thumbnail);
2795
+ * }
2796
+ * ```
2797
+ */
2798
+ async get(params) {
2799
+ return this.client.request("/v1/google/autocomplete", {
2800
+ params: { ...params }
2801
+ });
2802
+ }
2803
+ };
2804
+
2805
+ // src/google/finance.ts
2806
+ var FinanceClient = class {
2807
+ constructor(client) {
2808
+ this.client = client;
2809
+ }
2810
+ async quote(params) {
2811
+ return this.client.request("/v1/google/finance/quote", {
2812
+ params: { ...params }
2813
+ });
2814
+ }
2815
+ };
2816
+
2817
+ // src/google/flights.ts
2818
+ var FlightsClient = class {
2819
+ constructor(client) {
2820
+ this.client = client;
2821
+ }
2822
+ /** Search Google Flights for available itineraries. */
2823
+ async search(params) {
2824
+ return this.client.request("/v1/google/flights/search", {
2825
+ params: { ...params }
2826
+ });
2827
+ }
2828
+ };
2829
+
2830
+ // src/google/hotels.ts
2831
+ var HotelsClient = class {
2832
+ constructor(client) {
2833
+ this.client = client;
2834
+ }
2835
+ async search(params) {
2836
+ return this.client.request("/v1/google/hotels/search", {
2837
+ params: { ...params }
2838
+ });
2839
+ }
2840
+ async details(params) {
2841
+ return this.client.request("/v1/google/hotels/details", {
2842
+ params: { ...params }
2843
+ });
2844
+ }
2845
+ };
2846
+
2847
+ // src/google/images.ts
2848
+ var ImagesClient = class {
2849
+ constructor(client) {
2850
+ this.client = client;
2851
+ }
2852
+ async search(params) {
2853
+ return this.client.request("/v1/google/images/search", {
2854
+ params: { ...params }
2855
+ });
2856
+ }
2857
+ };
2858
+
2859
+ // src/google/jobs.ts
2860
+ var JobsClient = class {
2861
+ constructor(client) {
2862
+ this.client = client;
2863
+ }
2864
+ async search(params) {
2865
+ return this.client.request("/v1/google/jobs/search", {
2866
+ params: { ...params }
2867
+ });
2868
+ }
2869
+ };
2870
+
2871
+ // src/google/lens.ts
2872
+ var LensClient = class {
2873
+ constructor(client) {
2874
+ this.client = client;
2875
+ }
2876
+ async search(params) {
2877
+ return this.client.request("/v1/google/lens/search", {
2878
+ params: { ...params }
2879
+ });
2880
+ }
2881
+ };
2882
+
2883
+ // src/google/maps.ts
2884
+ var MapsClient = class {
2885
+ constructor(client) {
2886
+ this.client = client;
2887
+ }
2888
+ /**
2889
+ * Search Maps for places by text query, place_id, or ludocid.
2890
+ *
2891
+ * Returns up to 20 results per page with full details (place_id,
2892
+ * data_id, GPS, rating, reviews, address, phone, website, extensions,
2893
+ * weekly hours, thumbnail) in a single call.
2894
+ */
2895
+ async search(params) {
2896
+ if (!params.q && !params.place_id && !params.ludocid) {
2897
+ throw new Error("q, place_id, or ludocid is required");
2898
+ }
2899
+ return this.client.request("/v1/google/maps/search", {
2900
+ params: { ...params }
2901
+ });
2902
+ }
2903
+ /**
2904
+ * Get full place detail by `place_id` or `data_id`.
2905
+ *
2906
+ * Returns title, address, phone, website, GPS, rating, reviews_count,
2907
+ * rating_summary (per-star distribution), categories, extensions
2908
+ * (service_options, accessibility, offerings, payments), weekly
2909
+ * operating hours, popular_times graph, provider_id,
2910
+ * permanently_closed, thumbnail, and photo list.
2911
+ */
2912
+ async place(params) {
2913
+ if (!params.place_id && !params.data_id) {
2914
+ throw new Error("place_id or data_id is required");
2915
+ }
2916
+ return this.client.request("/v1/google/maps/place", {
2917
+ params: { ...params }
2918
+ });
2919
+ }
2920
+ /**
2921
+ * Get reviews for a place (paginated, optional topic filter).
2922
+ *
2923
+ * Pass the `next_page_token` from `response.pagination.next` for
2924
+ * subsequent pages, or use `topic_id` from `response.topics[].id`
2925
+ * to scope to a specific review topic.
2926
+ */
2927
+ async reviews(params) {
2928
+ return this.client.request("/v1/google/maps/reviews", {
2929
+ params: { ...params }
2930
+ });
2931
+ }
2932
+ /**
2933
+ * Get photos for a place with place-specific categories.
2934
+ *
2935
+ * Returns place-specific categories (Menu, Vibe, Comfort food, dish
2936
+ * names) and photo URLs from all CDN families. Use `category_id` to
2937
+ * scope to a category, or `page_size: 200` to fetch all photos in
2938
+ * one call (Google caps at ~120 photos per response).
2939
+ */
2940
+ async photos(params) {
2941
+ return this.client.request("/v1/google/maps/photos", {
2942
+ params: { ...params }
2943
+ });
2944
+ }
2945
+ /** Get business posts (promotional updates, announcements) for a place. */
2946
+ async posts(params) {
2947
+ if (!params.data_id && !params.place_id) {
2948
+ throw new Error("data_id or place_id is required");
2949
+ }
2950
+ return this.client.request("/v1/google/maps/posts", {
2951
+ params: { ...params }
2952
+ });
2953
+ }
2954
+ };
2955
+
2956
+ // src/google/news.ts
2957
+ var NewsClient = class {
2958
+ constructor(client) {
2959
+ this.client = client;
2960
+ }
2961
+ /**
2962
+ * Search Google News. One of `q`, `topic_token`, `publication_token`,
2963
+ * or `story_token` is required (or pass no params for the trending
2964
+ * home feed). Returns `menu_links`, `news_results`, `related_topics`.
2965
+ */
2966
+ async search(params = {}) {
2967
+ if (!params.q && !params.topic_token && !params.publication_token && !params.story_token) {
2968
+ throw new Error("Provide q, topic_token, publication_token, or story_token");
2969
+ }
2970
+ return this.client.request("/v1/google/news/search", {
2971
+ params: { ...params }
2972
+ });
2973
+ }
2974
+ async topics(params) {
2975
+ return this.client.request("/v1/google/news/topics", {
2976
+ params: { ...params }
2977
+ });
2978
+ }
2979
+ async trending(params = {}) {
2980
+ return this.client.request("/v1/google/news/trending", {
2981
+ params: { ...params }
2982
+ });
2983
+ }
2984
+ };
2985
+
2986
+ // src/google/patents.ts
2987
+ var PatentsClient = class {
2988
+ constructor(client) {
2989
+ this.client = client;
2990
+ }
2991
+ async search(params) {
2992
+ return this.client.request("/v1/google/patents/search", {
2993
+ params: { ...params }
2994
+ });
2995
+ }
2996
+ /**
2997
+ * Get rich patent document details by patent number.
2998
+ *
2999
+ * Response includes full abstract + every claim + complete description,
3000
+ * plus structured `cpc_classifications` (code + description), split
3001
+ * `backward_citations` / `forward_citations` (with `primary_examiner`
3002
+ * flag), `non_patent_citations`, `concepts` (research fields),
3003
+ * `legal_events` (prosecution history), `figures` (full-res URLs),
3004
+ * every `inventor`, and the full `assignees_original` history.
3005
+ */
3006
+ async detail(params) {
3007
+ return this.client.request("/v1/google/patents/detail", {
3008
+ params: { ...params }
3009
+ });
3010
+ }
3011
+ };
3012
+
3013
+ // src/google/products.ts
3014
+ var ProductsClient = class {
3015
+ constructor(client) {
3016
+ this.client = client;
3017
+ }
3018
+ async detail(params) {
3019
+ return this.client.request("/v1/google/products/detail", {
3020
+ params: { ...params }
3021
+ });
3022
+ }
3023
+ };
3024
+
3025
+ // src/google/scholar.ts
3026
+ var ScholarClient = class {
3027
+ constructor(client) {
3028
+ this.client = client;
3029
+ }
3030
+ /**
3031
+ * Search Google Scholar. Returns each result with doc `id`, `type`
3032
+ * badge, wrapped `inline_links`, PDF `resources`, and structured
3033
+ * authors. Envelope includes `scholar_results` alias,
3034
+ * `related_searches`, and matched `profiles` cards.
3035
+ */
3036
+ async search(params) {
3037
+ return this.client.request("/v1/google/scholar/search", {
3038
+ params: { ...params }
3039
+ });
3040
+ }
3041
+ /** Search Google Scholar for author profiles by name. */
3042
+ async profiles(params) {
3043
+ return this.client.request("/v1/google/scholar/profiles", {
3044
+ params: { ...params }
3045
+ });
3046
+ }
3047
+ /**
3048
+ * Full Scholar author profile: structured `interests_detailed`,
3049
+ * publications (with per-article `citation_id` + nested
3050
+ * `cited_by{value, link, citation_id}`), stats, and co-authors.
3051
+ */
3052
+ async author(params) {
3053
+ return this.client.request("/v1/google/scholar/author", {
3054
+ params: { ...params }
3055
+ });
3056
+ }
3057
+ /** Citations-per-year chart for a Scholar author. */
3058
+ async authorCitation(params) {
3059
+ return this.client.request("/v1/google/scholar/author/citation", {
3060
+ params: { ...params }
3061
+ });
3062
+ }
3063
+ /**
3064
+ * MLA / APA / Chicago / Harvard / Vancouver citation formats plus
3065
+ * BibTeX / RIS / EndNote / RefWorks export links for a paper.
3066
+ */
3067
+ async cite(params) {
3068
+ return this.client.request("/v1/google/scholar/cite", {
3069
+ params: { ...params }
3070
+ });
3071
+ }
3072
+ };
3073
+
3074
+ // src/google/search.ts
3075
+ var SearchClient2 = class {
3076
+ constructor(client) {
3077
+ this.client = client;
3078
+ }
3079
+ /**
3080
+ * Search Google and get a structured SERP response with organic results,
3081
+ * knowledge graph, People Also Ask, related searches, AI overview, and
3082
+ * pagination.
3083
+ */
3084
+ async search(params) {
3085
+ return this.client.request("/v1/google/search", { params: { ...params } });
3086
+ }
3087
+ /**
3088
+ * Lightweight Google Search — organic results + related searches only.
3089
+ *
3090
+ * ~40% faster than {@link search}. Skips ads, Knowledge Graph, AI
3091
+ * Overview, local pack, news, inline videos, and shopping blocks.
3092
+ * Credit cost is configured per-endpoint by admins — query
3093
+ * `/public/pricing` for the live rate.
3094
+ *
3095
+ * @example
3096
+ * ```typescript
3097
+ * const lite = await client.google.search.light({ q: "python 3.13" });
3098
+ * ```
3099
+ */
3100
+ async light(params) {
3101
+ return this.client.request("/v1/google/search", {
3102
+ params: { ...params, mode: "fast" }
3103
+ });
3104
+ }
3105
+ };
3106
+
3107
+ // src/google/shopping.ts
3108
+ var ShoppingClient = class {
3109
+ constructor(client) {
3110
+ this.client = client;
3111
+ }
3112
+ /** Search Google Shopping for products. */
3113
+ async search(params) {
3114
+ return this.client.request("/v1/google/shopping/search", {
3115
+ params: { ...params }
3116
+ });
3117
+ }
3118
+ /** Fetch the Google Shopping product detail page by `product_id`. */
3119
+ async product(params) {
3120
+ return this.client.request("/v1/google/shopping/product", {
3121
+ params: { ...params }
2312
3122
  });
2313
3123
  }
2314
3124
  /**
2315
- * Scrape using an existing session.
3125
+ * Resolve the direct merchant URL for a Shopping product tile via
3126
+ * Google's "I'm Feeling Lucky" redirect (scoped to the card's `source`
3127
+ * merchant via the `site:` operator). You only pay for the call when
3128
+ * you actually want the merchant link — no bulk enrichment of every
3129
+ * tile.
2316
3130
  */
2317
- async reuseSession(url, sessionId, options = {}) {
2318
- return this.scrape(url, { ...options, sessionId });
3131
+ async click(params) {
3132
+ return this.client.request("/v1/google/shopping/product/click", {
3133
+ params: { ...params }
3134
+ });
3135
+ }
3136
+ };
3137
+
3138
+ // src/google/shorts.ts
3139
+ var ShortsClient = class {
3140
+ constructor(client) {
3141
+ this.client = client;
3142
+ }
3143
+ async search(params) {
3144
+ return this.client.request("/v1/google/shorts/search", {
3145
+ params: { ...params }
3146
+ });
3147
+ }
3148
+ };
3149
+
3150
+ // src/google/trends.ts
3151
+ var TrendsClient2 = class {
3152
+ constructor(client) {
3153
+ this.client = client;
3154
+ }
3155
+ async interest(params) {
3156
+ return this.client.request("/v1/google/trends/interest", {
3157
+ params: { ...params }
3158
+ });
3159
+ }
3160
+ async regions(params) {
3161
+ return this.client.request("/v1/google/trends/regions", {
3162
+ params: { ...params }
3163
+ });
3164
+ }
3165
+ async related(params) {
3166
+ return this.client.request("/v1/google/trends/related", {
3167
+ params: { ...params }
3168
+ });
3169
+ }
3170
+ async trending(params = {}) {
3171
+ return this.client.request("/v1/google/trends/trending", {
3172
+ params: { ...params }
3173
+ });
3174
+ }
3175
+ /**
3176
+ * Current trending searches with the full Google Trends UI filter set
3177
+ * — `geo`, `hours`, `category`, `status`, `sort`, `hl`.
3178
+ */
3179
+ async trendingNow(params = {}) {
3180
+ return this.client.request("/v1/google/trends/trending-now", {
3181
+ params: { ...params }
3182
+ });
3183
+ }
3184
+ /**
3185
+ * Unified Google Trends query — pick the response shape via
3186
+ * `data_type` (TIMESERIES | GEO_MAP | GEO_MAP_0 | RELATED_TOPICS |
3187
+ * RELATED_QUERIES).
3188
+ */
3189
+ async search(params) {
3190
+ return this.client.request("/v1/google/trends/search", {
3191
+ params: { ...params }
3192
+ });
3193
+ }
3194
+ /**
3195
+ * Return categorized Knowledge Graph topic entities (`mid`, `type`,
3196
+ * direct link into Trends explore) for a query prefix. Distinct from
3197
+ * Google Search autocomplete.
3198
+ */
3199
+ async autocomplete(params) {
3200
+ return this.client.request("/v1/google/trends/autocomplete", {
3201
+ params: { ...params }
3202
+ });
3203
+ }
3204
+ };
3205
+
3206
+ // src/google/videos.ts
3207
+ var VideosClient = class {
3208
+ constructor(client) {
3209
+ this.client = client;
3210
+ }
3211
+ async search(params) {
3212
+ return this.client.request("/v1/google/videos/search", {
3213
+ params: { ...params }
3214
+ });
3215
+ }
3216
+ };
3217
+
3218
+ // src/google/client.ts
3219
+ var GoogleClient = class {
3220
+ /** Google Web Search (SERP) — with optional deferred AI Overview follow-up. */
3221
+ search;
3222
+ /** Google Maps — places, reviews, photos, posts. */
3223
+ maps;
3224
+ /** Google News — articles, topics, trending. */
3225
+ news;
3226
+ /** Google Hotels — search and property details. */
3227
+ hotels;
3228
+ /** Google Trends — interest, regions, related, trending, topic autocomplete. */
3229
+ trends;
3230
+ /** Google Jobs. */
3231
+ jobs;
3232
+ /** Google Shopping — search, details, click enrichment. */
3233
+ shopping;
3234
+ /** Google Patents — search and document details. */
3235
+ patents;
3236
+ /** Google Scholar — search, profiles, author, author citation, cite formats. */
3237
+ scholar;
3238
+ /** Google Autocomplete — search suggestions. */
3239
+ autocomplete;
3240
+ /** Google Images. */
3241
+ images;
3242
+ /** Google Videos. */
3243
+ videos;
3244
+ /** Google Finance — stock and index quotes. */
3245
+ finance;
3246
+ /** Google AI Mode — generative answer responses. */
3247
+ aiMode;
3248
+ /** Google Lens — visual image search. */
3249
+ lens;
3250
+ /** Google Shorts — short-form vertical video results (udm=39). */
3251
+ shorts;
3252
+ /** Google Flights — one-way, round-trip, and multi-city itineraries. */
3253
+ flights;
3254
+ /** Google Products — immersive product detail. */
3255
+ products;
3256
+ constructor(client) {
3257
+ this.search = new SearchClient2(client);
3258
+ this.maps = new MapsClient(client);
3259
+ this.news = new NewsClient(client);
3260
+ this.hotels = new HotelsClient(client);
3261
+ this.trends = new TrendsClient2(client);
3262
+ this.jobs = new JobsClient(client);
3263
+ this.shopping = new ShoppingClient(client);
3264
+ this.patents = new PatentsClient(client);
3265
+ this.scholar = new ScholarClient(client);
3266
+ this.autocomplete = new AutocompleteClient(client);
3267
+ this.images = new ImagesClient(client);
3268
+ this.videos = new VideosClient(client);
3269
+ this.finance = new FinanceClient(client);
3270
+ this.aiMode = new AiModeClient(client);
3271
+ this.lens = new LensClient(client);
3272
+ this.shorts = new ShortsClient(client);
3273
+ this.flights = new FlightsClient(client);
3274
+ this.products = new ProductsClient(client);
2319
3275
  }
2320
3276
  };
2321
3277
 
@@ -2326,6 +3282,10 @@ var ScrapeBadger = class {
2326
3282
  twitter;
2327
3283
  /** Web scraping API client */
2328
3284
  web;
3285
+ /** Vinted scraper API client */
3286
+ vinted;
3287
+ /** Google Scraper API client — 19 Google product APIs */
3288
+ google;
2329
3289
  /**
2330
3290
  * Create a new ScrapeBadger client.
2331
3291
  *
@@ -2362,6 +3322,8 @@ var ScrapeBadger = class {
2362
3322
  this.baseClient = new BaseClient(resolvedConfig);
2363
3323
  this.twitter = new TwitterClient(this.baseClient);
2364
3324
  this.web = new WebClient(this.baseClient);
3325
+ this.vinted = new VintedClient(this.baseClient);
3326
+ this.google = new GoogleClient(this.baseClient);
2365
3327
  }
2366
3328
  };
2367
3329
 
@@ -2370,6 +3332,25 @@ exports.AuthenticationError = AuthenticationError;
2370
3332
  exports.CommunitiesClient = CommunitiesClient;
2371
3333
  exports.ConflictError = ConflictError;
2372
3334
  exports.GeoClient = GeoClient;
3335
+ exports.GoogleAiModeClient = AiModeClient;
3336
+ exports.GoogleAutocompleteClient = AutocompleteClient;
3337
+ exports.GoogleClient = GoogleClient;
3338
+ exports.GoogleFinanceClient = FinanceClient;
3339
+ exports.GoogleFlightsClient = FlightsClient;
3340
+ exports.GoogleHotelsClient = HotelsClient;
3341
+ exports.GoogleImagesClient = ImagesClient;
3342
+ exports.GoogleJobsClient = JobsClient;
3343
+ exports.GoogleLensClient = LensClient;
3344
+ exports.GoogleMapsClient = MapsClient;
3345
+ exports.GoogleNewsClient = NewsClient;
3346
+ exports.GooglePatentsClient = PatentsClient;
3347
+ exports.GoogleProductsClient = ProductsClient;
3348
+ exports.GoogleScholarClient = ScholarClient;
3349
+ exports.GoogleSearchClient = SearchClient2;
3350
+ exports.GoogleShoppingClient = ShoppingClient;
3351
+ exports.GoogleShortsClient = ShortsClient;
3352
+ exports.GoogleTrendsClient = TrendsClient2;
3353
+ exports.GoogleVideosClient = VideosClient;
2373
3354
  exports.InsufficientCreditsError = InsufficientCreditsError;
2374
3355
  exports.ListsClient = ListsClient;
2375
3356
  exports.NotFoundError = NotFoundError;
@@ -2377,6 +3358,7 @@ exports.RateLimitError = RateLimitError;
2377
3358
  exports.ScrapeBadger = ScrapeBadger;
2378
3359
  exports.ScrapeBadgerError = ScrapeBadgerError;
2379
3360
  exports.ServerError = ServerError;
3361
+ exports.SpacesClient = SpacesClient;
2380
3362
  exports.StreamClient = StreamClient;
2381
3363
  exports.TimeoutError = TimeoutError;
2382
3364
  exports.TrendsClient = TrendsClient;
@@ -2384,6 +3366,11 @@ exports.TweetsClient = TweetsClient;
2384
3366
  exports.TwitterClient = TwitterClient;
2385
3367
  exports.UsersClient = UsersClient;
2386
3368
  exports.ValidationError = ValidationError;
3369
+ exports.VintedClient = VintedClient;
3370
+ exports.VintedItemsClient = ItemsClient;
3371
+ exports.VintedReferenceClient = ReferenceClient;
3372
+ exports.VintedSearchClient = SearchClient;
3373
+ exports.VintedUsersClient = UsersClient2;
2387
3374
  exports.WebClient = WebClient;
2388
3375
  exports.WebSocketStreamError = WebSocketStreamError;
2389
3376
  exports.collectAll = collectAll;