scrapebadger 0.4.0 → 0.8.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.d.ts CHANGED
@@ -6,100 +6,99 @@ import 'node:events';
6
6
  * TypeScript types for web scraping API responses.
7
7
  */
8
8
  interface ScrapeOptions {
9
+ /** Output format */
10
+ format?: "html" | "markdown" | "text";
9
11
  /** Whether to render JavaScript */
10
12
  renderJs?: boolean;
11
- /** Output format (html, markdown, text, json) */
12
- outputFormat?: "html" | "markdown" | "text" | "json";
13
- /** Country code for proxy (e.g. "US") */
14
- proxyCountry?: string;
15
- /** Proxy type (datacenter, residential) */
16
- proxyType?: "datacenter" | "residential" | "mobile" | "isp";
17
- /** Reuse an existing session */
18
- sessionId?: string;
19
- /** Force a specific engine */
20
- engine?: string;
21
- /** Maximum credit cost */
22
- maxCost?: number;
23
- /** Custom HTTP headers */
24
- headers?: Record<string, string>;
25
- /** CSS selector to wait for */
13
+ /** Force a specific engine (auto, browser) */
14
+ engine?: "auto" | "browser";
15
+ /** CSS selector or XPath to wait for */
26
16
  waitFor?: string;
27
- /** Request timeout in seconds */
28
- timeout?: number;
29
- /** JavaScript actions to execute */
17
+ /** Timeout in ms for waitFor selector (1000-120000) */
18
+ waitTimeout?: number;
19
+ /** Additional ms to wait after page load (0-30000) */
20
+ waitAfterLoad?: number;
21
+ /** Browser actions to perform before extracting */
30
22
  jsScenario?: Array<Record<string, unknown>>;
31
- }
32
- interface ScreenshotOptions {
33
- /** Capture full page (not just viewport) */
34
- fullPage?: boolean;
35
- /** Viewport width in pixels */
36
- viewportWidth?: number;
37
- /** Viewport height in pixels */
38
- viewportHeight?: number;
39
- /** Image format (png, jpeg) */
40
- imageFormat?: "png" | "jpeg";
41
- /** CSS selector to wait for */
42
- waitFor?: string;
43
- /** Request timeout in seconds */
44
- timeout?: number;
45
- }
46
- interface ExtractOptions {
47
- /** Extraction schema (CSS/XPath selectors) */
48
- schema?: Record<string, unknown>;
49
- /** Whether to render JavaScript */
50
- renderJs?: boolean;
51
- /** CSS selector to wait for */
52
- waitFor?: string;
53
- /** Request timeout in seconds */
54
- timeout?: number;
55
- }
56
- interface BatchOptions {
57
- /** Whether to render JavaScript */
58
- renderJs?: boolean;
59
- /** Output format */
60
- outputFormat?: "html" | "markdown" | "text" | "json";
61
- /** Maximum concurrent requests */
62
- maxConcurrency?: number;
63
- /** Force a specific engine */
64
- engine?: string;
65
- /** Request timeout in seconds */
66
- timeout?: number;
23
+ /** Session ID for persistent cookies/state */
24
+ sessionId?: string;
25
+ /** Max retry attempts on blocking (0-10) */
26
+ retryCount?: number;
27
+ /** Auto-retry on blocking detection */
28
+ retryOnBlock?: boolean;
29
+ /** ISO country code for proxy geo-targeting */
30
+ country?: string;
31
+ /** Custom HTTP headers */
32
+ customHeaders?: Record<string, string>;
33
+ /** Capture full-page screenshot */
34
+ screenshot?: boolean;
35
+ /** Record browser session as video (+3 credits) */
36
+ video?: boolean;
37
+ /** Attempt anti-bot bypass */
38
+ antiBot?: boolean;
39
+ /** Allow auto-escalation to stronger engines */
40
+ escalate?: boolean;
41
+ /** Maximum credits budget */
42
+ maxCost?: number;
43
+ /** Run AI extraction on content */
44
+ aiExtract?: boolean;
45
+ /** Natural language prompt for AI extraction (max 2000 chars) */
46
+ aiPrompt?: string;
47
+ /**
48
+ * When true, the server streams the raw body as `text/html` with
49
+ * metadata in `X-Scrape-*` response headers instead of JSON-wrapping
50
+ * the content. Saves 300–1000 ms on large (>1 MB) pages. Incompatible
51
+ * with `aiExtract`, `screenshot`, `video`.
52
+ */
53
+ rawContent?: boolean;
54
+ /**
55
+ * When true, the server skips the generic blocking-page + anti-bot /
56
+ * CAPTCHA regex scans on the response body. Saves ~1.3 s on large
57
+ * responses. Only safe for origins known not to use consumer WAFs
58
+ * (Cloudflare, DataDome, Akamai, Kasada). Default false — keep
59
+ * disabled for general-purpose scraping.
60
+ */
61
+ skipBotDetection?: boolean;
67
62
  }
68
63
  interface ScrapeResult {
69
- content: string;
70
- status_code: number;
64
+ success: boolean;
71
65
  url: string;
72
- engine_used?: string;
73
- credits_used: number;
74
- processing_time_ms?: number;
75
- anti_bot_detected: boolean;
76
- anti_bot_provider?: string;
77
- captcha_solved: boolean;
78
- session_id?: string;
79
- session_reused: boolean;
80
- }
81
- interface ScreenshotResult {
82
- image_data: string;
66
+ status_code: number;
67
+ content: string | null;
83
68
  format: string;
84
- url: string;
69
+ engine_used: string;
85
70
  credits_used: number;
71
+ duration_ms: number;
72
+ retries_used: number;
73
+ content_length: number;
74
+ screenshot_url: string | null;
75
+ video_url: string | null;
76
+ headers: Record<string, string>;
77
+ blocking_detected: boolean;
78
+ blocking_details: Record<string, unknown> | null;
79
+ antibot_systems: Array<Record<string, unknown>>;
80
+ captcha_systems: Array<Record<string, unknown>>;
81
+ anti_bot_solved: boolean;
82
+ solver_used: string | null;
83
+ ai_extraction: Record<string, unknown> | string | unknown[] | null;
84
+ ai_model: string | null;
85
+ ai_error: string | null;
86
+ }
87
+ interface DetectOptions {
88
+ /** Request timeout in ms (1000-60000) */
89
+ timeout?: number;
90
+ /** ISO country code for proxy geo-targeting */
91
+ country?: string;
86
92
  }
87
- interface ExtractResult {
88
- data: Record<string, unknown>;
93
+ interface DetectResult {
89
94
  url: string;
95
+ antibot_systems: Array<Record<string, unknown>>;
96
+ captcha_systems: Array<Record<string, unknown>>;
97
+ is_blocked: boolean;
98
+ blocking_type: string | null;
99
+ recommendation: string | null;
90
100
  credits_used: number;
91
- }
92
- interface BatchResult {
93
- results: ScrapeResult[];
94
- total: number;
95
- successful: number;
96
- failed: number;
97
- }
98
- interface SessionInfo {
99
- session_id: string;
100
- domain: string;
101
- reused: boolean;
102
- fingerprint_id?: string;
101
+ duration_ms: number;
103
102
  }
104
103
 
105
104
  /**
@@ -114,19 +113,24 @@ interface SessionInfo {
114
113
  * const client = new ScrapeBadger({ apiKey: "key" });
115
114
  *
116
115
  * // Simple scrape
117
- * const result = await client.web.scrape("https://example.com");
116
+ * const result = await client.web.scrape("https://scrapebadger.com");
118
117
  * console.log(result.content);
119
118
  *
120
- * // Screenshot
121
- * const screenshot = await client.web.screenshot("https://example.com");
122
- *
123
- * // Extract structured data
124
- * const data = await client.web.extract("https://example.com", {
125
- * schema: { title: "css:h1" }
119
+ * // Scrape with JavaScript rendering
120
+ * const rendered = await client.web.scrape("https://scrapebadger.com", {
121
+ * renderJs: true,
122
+ * format: "markdown",
126
123
  * });
127
124
  *
128
- * // Batch scrape
129
- * const batch = await client.web.batch(["https://a.com", "https://b.com"]);
125
+ * // AI extraction
126
+ * const extracted = await client.web.extract(
127
+ * "https://scrapebadger.com/pricing",
128
+ * "Extract all pricing plans with their features"
129
+ * );
130
+ *
131
+ * // Detect anti-bot systems
132
+ * const detection = await client.web.detect("https://scrapebadger.com");
133
+ * console.log(detection.antibot_systems);
130
134
  * ```
131
135
  */
132
136
  declare class WebClient {
@@ -134,28 +138,3203 @@ declare class WebClient {
134
138
  constructor(client: BaseClient);
135
139
  /**
136
140
  * Scrape a web page.
141
+ *
142
+ * @param url - The URL to scrape
143
+ * @param options - Scrape configuration options
144
+ * @returns The scrape result including content, metadata, and credit usage
137
145
  */
138
146
  scrape(url: string, options?: ScrapeOptions): Promise<ScrapeResult>;
139
147
  /**
140
- * Take a screenshot of a web page.
148
+ * Extract structured data from a web page using AI.
149
+ *
150
+ * Convenience wrapper around {@link scrape} that enables AI extraction
151
+ * with the given prompt and defaults to markdown format.
152
+ *
153
+ * @param url - The URL to extract data from
154
+ * @param prompt - Natural language prompt describing what to extract (max 2000 chars)
155
+ * @param options - Additional scrape options (aiExtract and aiPrompt are set automatically)
156
+ * @returns The scrape result with ai_extraction populated
157
+ */
158
+ extract(url: string, prompt: string, options?: ScrapeOptions): Promise<ScrapeResult>;
159
+ /**
160
+ * Detect anti-bot systems on a URL.
161
+ *
162
+ * @param url - The URL to analyze
163
+ * @param options - Detection options
164
+ * @returns Detection results including identified anti-bot and captcha systems
165
+ */
166
+ detect(url: string, options?: DetectOptions): Promise<DetectResult>;
167
+ }
168
+
169
+ /**
170
+ * TypeScript types for Vinted API responses.
171
+ *
172
+ * This module contains all the data types used by the Vinted API client.
173
+ */
174
+ /**
175
+ * A price with amount and currency.
176
+ */
177
+ interface VintedPrice {
178
+ /** Price amount as a string (e.g. "12.50") */
179
+ amount: string;
180
+ /** ISO currency code (e.g. "EUR") */
181
+ currency_code: string;
182
+ }
183
+ /**
184
+ * A photo attached to a Vinted item.
185
+ */
186
+ interface VintedPhoto {
187
+ /** Unique photo identifier */
188
+ id: number;
189
+ /** Photo URL */
190
+ url: string;
191
+ /** Dominant color hex code */
192
+ dominant_color: string | null;
193
+ /** Whether this is the main/cover photo */
194
+ is_main: boolean;
195
+ /** Image width in pixels */
196
+ width: number | null;
197
+ /** Image height in pixels */
198
+ height: number | null;
199
+ /** Full resolution image URL */
200
+ full_size_url: string | null;
201
+ }
202
+ /**
203
+ * Brief user information shown on item listings.
204
+ */
205
+ interface VintedUserSummary {
206
+ /** Unique user identifier */
207
+ id: number;
208
+ /** Username / login handle */
209
+ login: string;
210
+ /** Profile photo URL */
211
+ photo_url: string | null;
212
+ /** Whether the user is a business account */
213
+ business: boolean;
214
+ }
215
+ /**
216
+ * Seller summary with feedback and item stats.
217
+ */
218
+ interface VintedSellerSummary extends VintedUserSummary {
219
+ /** Total number of feedback ratings */
220
+ feedback_count: number;
221
+ /** Overall feedback reputation score (0-1) */
222
+ feedback_reputation: number;
223
+ /** Number of items listed */
224
+ item_count: number;
225
+ /** Seller's location */
226
+ location: string | null;
227
+ /** Last activity timestamp (ISO format) */
228
+ last_seen: string | null;
229
+ /** Achievement badges */
230
+ badges: string[];
231
+ }
232
+ /**
233
+ * A Vinted item summary as returned in search results and listings.
234
+ */
235
+ interface VintedItemSummary {
236
+ /** Unique item identifier */
237
+ id: number;
238
+ /** Item title */
239
+ title: string;
240
+ /** Item price */
241
+ price: VintedPrice;
242
+ /** Brand name */
243
+ brand_title: string;
244
+ /** Size label */
245
+ size_title: string;
246
+ /** Item condition status */
247
+ status: string;
248
+ /** Item URL on Vinted */
249
+ url: string;
250
+ /** Number of users who favorited this item */
251
+ favourite_count: number;
252
+ /** Number of views */
253
+ view_count: number;
254
+ /** Item owner summary */
255
+ user: VintedUserSummary;
256
+ /** Main photo */
257
+ photo: VintedPhoto;
258
+ /** All photos */
259
+ photos: VintedPhoto[];
260
+ }
261
+ /**
262
+ * Full item detail with all metadata.
263
+ */
264
+ interface VintedItemDetail extends VintedItemSummary {
265
+ /** Item description */
266
+ description: string;
267
+ /** Catalog category identifier */
268
+ catalog_id: number;
269
+ /** Primary color */
270
+ color1: string;
271
+ /** Seller details */
272
+ seller: VintedSellerSummary;
273
+ /** Category name */
274
+ category: string;
275
+ /** Upload timestamp (ISO format) */
276
+ upload_date: string;
277
+ /** Whether the item can be purchased */
278
+ can_buy: boolean;
279
+ /** Whether instant buy is enabled */
280
+ instant_buy: boolean;
281
+ /** Whether the listing is closed */
282
+ is_closed: boolean;
283
+ /** Whether the item is reserved */
284
+ is_reserved: boolean;
285
+ /** Whether the item is hidden */
286
+ is_hidden: boolean;
287
+ /** Size identifier */
288
+ size_id: number;
289
+ /** Status identifier */
290
+ status_id: number;
291
+ /** Brand identifier */
292
+ brand_id: number;
293
+ }
294
+ /**
295
+ * Full Vinted user profile.
296
+ */
297
+ interface VintedUserProfile {
298
+ /** Unique user identifier */
299
+ id: number;
300
+ /** Username / login handle */
301
+ login: string;
302
+ /** Profile photo URL */
303
+ photo_url: string | null;
304
+ /** Whether the user is a business account */
305
+ business: boolean;
306
+ /** ISO country code */
307
+ country_code: string;
308
+ /** City name */
309
+ city: string;
310
+ /** Total feedback count */
311
+ feedback_count: number;
312
+ /** Overall feedback reputation (0-1) */
313
+ feedback_reputation: number;
314
+ /** Number of positive ratings */
315
+ positive_feedback_count: number;
316
+ /** Number of neutral ratings */
317
+ neutral_feedback_count: number;
318
+ /** Number of negative ratings */
319
+ negative_feedback_count: number;
320
+ /** Number of items listed */
321
+ item_count: number;
322
+ /** Number of followers */
323
+ followers_count: number;
324
+ /** Number of users this user follows */
325
+ following_count: number;
326
+ /** Whether the user is currently online */
327
+ is_online: boolean;
328
+ /** Whether the user is on holiday mode */
329
+ is_on_holiday: boolean;
330
+ /** Last login timestamp (Unix) */
331
+ last_loged_on_ts: string;
332
+ /** Full profile URL */
333
+ profile_url: string;
334
+ /** User locale */
335
+ locale: string;
336
+ }
337
+ /**
338
+ * A Vinted brand.
339
+ */
340
+ interface VintedBrand {
341
+ /** Unique brand identifier */
342
+ id: number;
343
+ /** Brand name */
344
+ title: string;
345
+ /** URL-friendly slug */
346
+ slug: string;
347
+ /** Number of items with this brand */
348
+ item_count: number;
349
+ /** Number of users who favorited this brand */
350
+ favourite_count: number;
351
+ /** Whether the brand is classified as luxury */
352
+ is_luxury: boolean;
353
+ /** Brand page URL */
354
+ url: string;
355
+ }
356
+ /**
357
+ * A Vinted color option.
358
+ */
359
+ interface VintedColor {
360
+ /** Unique color identifier */
361
+ id: number;
362
+ /** Color display name */
363
+ title: string;
364
+ /** Hex color code */
365
+ hex: string;
366
+ /** Internal color code */
367
+ code: string;
368
+ }
369
+ /**
370
+ * A Vinted item condition status.
371
+ */
372
+ interface VintedStatus {
373
+ /** Unique status identifier */
374
+ id: number;
375
+ /** Status display name */
376
+ title: string;
377
+ }
378
+ /**
379
+ * A Vinted marketplace/country.
380
+ */
381
+ interface VintedMarket {
382
+ /** Market code (e.g. "fr", "de") */
383
+ code: string;
384
+ /** Vinted domain for this market */
385
+ domain: string;
386
+ /** Country name */
387
+ country: string;
388
+ /** Currency code */
389
+ currency: string;
390
+ /** Market display name */
391
+ name: string;
392
+ }
393
+ /**
394
+ * Pagination metadata for list responses.
395
+ */
396
+ interface VintedPagination {
397
+ /** Current page number */
398
+ current_page: number;
399
+ /** Total number of pages */
400
+ total_pages: number;
401
+ /** Total number of entries */
402
+ total_entries: number;
403
+ /** Items per page */
404
+ per_page: number;
405
+ }
406
+ /**
407
+ * Response from the search endpoint.
408
+ */
409
+ interface SearchResponse {
410
+ /** List of matching items */
411
+ items: VintedItemSummary[];
412
+ /** Pagination metadata */
413
+ pagination: VintedPagination;
414
+ /** Market code used for this search */
415
+ market: string;
416
+ }
417
+ /**
418
+ * Response from the item detail endpoint.
419
+ */
420
+ interface ItemDetailResponse {
421
+ /** Full item details */
422
+ item: VintedItemDetail;
423
+ /** Market code used */
424
+ market: string;
425
+ }
426
+ /**
427
+ * Response from the user profile endpoint.
428
+ */
429
+ interface UserProfileResponse$1 {
430
+ /** Full user profile */
431
+ user: VintedUserProfile;
432
+ /** Market code used */
433
+ market: string;
434
+ }
435
+ /**
436
+ * Response from the user items endpoint.
437
+ */
438
+ interface UserItemsResponse {
439
+ /** List of user's items */
440
+ items: VintedItemSummary[];
441
+ /** Pagination metadata */
442
+ pagination: VintedPagination;
443
+ /** Market code used */
444
+ market: string;
445
+ }
446
+ /**
447
+ * Response from the brands endpoint.
448
+ */
449
+ interface BrandsResponse {
450
+ /** List of brands */
451
+ brands: VintedBrand[];
452
+ /** Pagination metadata (null when no pagination) */
453
+ pagination: VintedPagination | null;
454
+ }
455
+ /**
456
+ * Response from the colors endpoint.
457
+ */
458
+ interface ColorsResponse {
459
+ /** List of available colors */
460
+ colors: VintedColor[];
461
+ }
462
+ /**
463
+ * Response from the statuses endpoint.
464
+ */
465
+ interface StatusesResponse {
466
+ /** List of item condition statuses */
467
+ statuses: VintedStatus[];
468
+ }
469
+ /**
470
+ * Response from the markets endpoint.
471
+ */
472
+ interface MarketsResponse {
473
+ /** List of available markets */
474
+ markets: VintedMarket[];
475
+ }
476
+ /**
477
+ * Parameters for searching Vinted items.
478
+ */
479
+ interface VintedSearchParams {
480
+ /** Search query string */
481
+ query: string;
482
+ /** Market code (default: "fr") */
483
+ market?: string;
484
+ /** Page number */
485
+ page?: number;
486
+ /** Items per page */
487
+ per_page?: number;
488
+ /** Minimum price filter */
489
+ price_from?: number;
490
+ /** Maximum price filter */
491
+ price_to?: number;
492
+ /** Comma-separated brand IDs */
493
+ brand_ids?: string;
494
+ /** Comma-separated color IDs */
495
+ color_ids?: string;
496
+ /** Comma-separated status IDs */
497
+ status_ids?: string;
498
+ /** Sort order */
499
+ order?: "relevance" | "newest_first" | "price_low_to_high" | "price_high_to_low";
500
+ }
501
+
502
+ /**
503
+ * Vinted Search API client.
504
+ *
505
+ * Provides methods for searching Vinted item listings.
506
+ */
507
+
508
+ /**
509
+ * Client for Vinted search endpoints.
510
+ *
511
+ * @example
512
+ * ```typescript
513
+ * const client = new ScrapeBadger({ apiKey: "key" });
514
+ *
515
+ * // Basic search
516
+ * const results = await client.vinted.search.search({ query: "nike air max" });
517
+ * for (const item of results.items) {
518
+ * console.log(`${item.title} — ${item.price.amount} ${item.price.currency_code}`);
519
+ * }
520
+ *
521
+ * // Search with filters
522
+ * const filtered = await client.vinted.search.search({
523
+ * query: "adidas",
524
+ * market: "de",
525
+ * price_from: 10,
526
+ * price_to: 50,
527
+ * order: "price_low_to_high",
528
+ * });
529
+ * ```
530
+ */
531
+ declare class SearchClient$2 {
532
+ private readonly client;
533
+ constructor(client: BaseClient);
534
+ /**
535
+ * Search for Vinted items.
536
+ *
537
+ * @param params - Search parameters including query, filters, and pagination.
538
+ * @returns Search results with items and pagination metadata.
539
+ * @throws AuthenticationError - If the API key is invalid.
540
+ * @throws ValidationError - If the search parameters are invalid.
541
+ *
542
+ * @example
543
+ * ```typescript
544
+ * const results = await client.vinted.search.search({
545
+ * query: "vintage jacket",
546
+ * market: "fr",
547
+ * page: 1,
548
+ * per_page: 20,
549
+ * order: "newest_first",
550
+ * });
551
+ * console.log(`Found ${results.pagination.total_entries} items`);
552
+ * ```
553
+ */
554
+ search(params: VintedSearchParams): Promise<SearchResponse>;
555
+ }
556
+
557
+ /**
558
+ * Vinted Items API client.
559
+ *
560
+ * Provides methods for fetching individual Vinted item details.
561
+ */
562
+
563
+ /**
564
+ * Client for Vinted item endpoints.
565
+ *
566
+ * @example
567
+ * ```typescript
568
+ * const client = new ScrapeBadger({ apiKey: "key" });
569
+ *
570
+ * const item = await client.vinted.items.get(123456789, { market: "fr" });
571
+ * console.log(`${item.item.title} — ${item.item.price.amount} ${item.item.price.currency_code}`);
572
+ * console.log(`Seller: ${item.item.seller.login}`);
573
+ * ```
574
+ */
575
+ declare class ItemsClient {
576
+ private readonly client;
577
+ constructor(client: BaseClient);
578
+ /**
579
+ * Get a single item by ID.
580
+ *
581
+ * @param itemId - The Vinted item ID to fetch.
582
+ * @param options - Optional parameters.
583
+ * @param options.market - Market code (default: "fr").
584
+ * @returns The item detail response including full item data.
585
+ * @throws NotFoundError - If the item doesn't exist.
586
+ * @throws AuthenticationError - If the API key is invalid.
587
+ *
588
+ * @example
589
+ * ```typescript
590
+ * const response = await client.vinted.items.get(123456789);
591
+ * const { item } = response;
592
+ * console.log(`${item.title}: ${item.description}`);
593
+ * console.log(`Brand: ${item.brand_title}, Size: ${item.size_title}`);
594
+ * console.log(`Photos: ${item.photos.length}`);
595
+ * ```
596
+ */
597
+ get(itemId: number, options?: {
598
+ market?: string;
599
+ }): Promise<ItemDetailResponse>;
600
+ }
601
+
602
+ /**
603
+ * Vinted Users API client.
604
+ *
605
+ * Provides methods for fetching Vinted user profiles and their item listings.
606
+ */
607
+
608
+ /**
609
+ * Client for Vinted user endpoints.
610
+ *
611
+ * @example
612
+ * ```typescript
613
+ * const client = new ScrapeBadger({ apiKey: "key" });
614
+ *
615
+ * // Get user profile
616
+ * const profile = await client.vinted.users.getProfile(12345);
617
+ * console.log(`${profile.user.login} — ${profile.user.item_count} items`);
618
+ *
619
+ * // Get user's items
620
+ * const items = await client.vinted.users.getItems(12345);
621
+ * for (const item of items.items) {
622
+ * console.log(`${item.title} — ${item.price.amount} ${item.price.currency_code}`);
623
+ * }
624
+ * ```
625
+ */
626
+ declare class UsersClient$1 {
627
+ private readonly client;
628
+ constructor(client: BaseClient);
629
+ /**
630
+ * Get a user's profile.
631
+ *
632
+ * @param userId - The Vinted user ID.
633
+ * @param options - Optional parameters.
634
+ * @param options.market - Market code (default: "fr").
635
+ * @returns The user profile response.
636
+ * @throws NotFoundError - If the user doesn't exist.
637
+ * @throws AuthenticationError - If the API key is invalid.
638
+ *
639
+ * @example
640
+ * ```typescript
641
+ * const response = await client.vinted.users.getProfile(12345);
642
+ * const { user } = response;
643
+ * console.log(`${user.login} from ${user.city}, ${user.country_code}`);
644
+ * console.log(`Reputation: ${user.feedback_reputation}`);
645
+ * console.log(`Items: ${user.item_count}, Followers: ${user.followers_count}`);
646
+ * ```
647
+ */
648
+ getProfile(userId: number, options?: {
649
+ market?: string;
650
+ }): Promise<UserProfileResponse$1>;
651
+ /**
652
+ * Get items listed by a user.
653
+ *
654
+ * @param userId - The Vinted user ID.
655
+ * @param options - Optional parameters for pagination and market.
656
+ * @param options.market - Market code (default: "fr").
657
+ * @param options.page - Page number.
658
+ * @param options.per_page - Items per page.
659
+ * @returns The user's items with pagination metadata.
660
+ * @throws NotFoundError - If the user doesn't exist.
661
+ * @throws AuthenticationError - If the API key is invalid.
662
+ *
663
+ * @example
664
+ * ```typescript
665
+ * const response = await client.vinted.users.getItems(12345, {
666
+ * market: "de",
667
+ * page: 1,
668
+ * per_page: 20,
669
+ * });
670
+ * console.log(`Page ${response.pagination.current_page} of ${response.pagination.total_pages}`);
671
+ * for (const item of response.items) {
672
+ * console.log(`${item.title} — ${item.price.amount} ${item.price.currency_code}`);
673
+ * }
674
+ * ```
141
675
  */
142
- screenshot(url: string, options?: ScreenshotOptions): Promise<ScreenshotResult>;
676
+ getItems(userId: number, options?: {
677
+ market?: string;
678
+ page?: number;
679
+ per_page?: number;
680
+ }): Promise<UserItemsResponse>;
681
+ }
682
+
683
+ /**
684
+ * Vinted Reference Data API client.
685
+ *
686
+ * Provides methods for fetching brands, colors, statuses, and markets.
687
+ */
688
+
689
+ /**
690
+ * Client for Vinted reference data endpoints.
691
+ *
692
+ * @example
693
+ * ```typescript
694
+ * const client = new ScrapeBadger({ apiKey: "key" });
695
+ *
696
+ * // Get available markets
697
+ * const markets = await client.vinted.reference.markets();
698
+ * for (const market of markets.markets) {
699
+ * console.log(`${market.name} (${market.code}) — ${market.currency}`);
700
+ * }
701
+ *
702
+ * // Search brands
703
+ * const brands = await client.vinted.reference.brands({ keyword: "nike" });
704
+ * for (const brand of brands.brands) {
705
+ * console.log(`${brand.title}: ${brand.item_count} items`);
706
+ * }
707
+ * ```
708
+ */
709
+ declare class ReferenceClient {
710
+ private readonly client;
711
+ constructor(client: BaseClient);
143
712
  /**
144
- * Extract structured data from a web page.
713
+ * Search for brands by keyword.
714
+ *
715
+ * @param options - Optional parameters.
716
+ * @param options.keyword - Brand name to search for.
717
+ * @param options.market - Market code (default: "fr").
718
+ * @param options.per_page - Number of results per page.
719
+ * @returns Brands matching the keyword.
720
+ *
721
+ * @example
722
+ * ```typescript
723
+ * const response = await client.vinted.reference.brands({
724
+ * keyword: "adidas",
725
+ * market: "de",
726
+ * per_page: 10,
727
+ * });
728
+ * for (const brand of response.brands) {
729
+ * console.log(`${brand.title} (${brand.slug}): ${brand.item_count} items`);
730
+ * }
731
+ * ```
145
732
  */
146
- extract(url: string, options?: ExtractOptions): Promise<ExtractResult>;
733
+ brands(options?: {
734
+ keyword?: string;
735
+ market?: string;
736
+ per_page?: number;
737
+ }): Promise<BrandsResponse>;
147
738
  /**
148
- * Scrape multiple URLs in a batch.
739
+ * Get available colors for a market.
740
+ *
741
+ * @param options - Optional parameters.
742
+ * @param options.market - Market code (default: "fr").
743
+ * @returns List of available colors.
744
+ *
745
+ * @example
746
+ * ```typescript
747
+ * const response = await client.vinted.reference.colors({ market: "fr" });
748
+ * for (const color of response.colors) {
749
+ * console.log(`${color.title} (#${color.hex})`);
750
+ * }
751
+ * ```
149
752
  */
150
- batch(urls: string[], options?: BatchOptions): Promise<BatchResult>;
753
+ colors(options?: {
754
+ market?: string;
755
+ }): Promise<ColorsResponse>;
151
756
  /**
152
- * Create a new scraping session for a domain.
757
+ * Get available item condition statuses for a market.
758
+ *
759
+ * @param options - Optional parameters.
760
+ * @param options.market - Market code (default: "fr").
761
+ * @returns List of item condition statuses.
762
+ *
763
+ * @example
764
+ * ```typescript
765
+ * const response = await client.vinted.reference.statuses({ market: "fr" });
766
+ * for (const status of response.statuses) {
767
+ * console.log(`${status.id}: ${status.title}`);
768
+ * }
769
+ * ```
153
770
  */
154
- createSession(domain: string, persist?: boolean): Promise<SessionInfo>;
771
+ statuses(options?: {
772
+ market?: string;
773
+ }): Promise<StatusesResponse>;
155
774
  /**
156
- * Scrape using an existing session.
775
+ * Get all available Vinted markets.
776
+ *
777
+ * @returns List of all supported Vinted markets/countries.
778
+ *
779
+ * @example
780
+ * ```typescript
781
+ * const response = await client.vinted.reference.markets();
782
+ * for (const market of response.markets) {
783
+ * console.log(`${market.name}: ${market.domain} (${market.currency})`);
784
+ * }
785
+ * ```
157
786
  */
158
- reuseSession(url: string, sessionId: string, options?: ScrapeOptions): Promise<ScrapeResult>;
787
+ markets(): Promise<MarketsResponse>;
788
+ }
789
+
790
+ /**
791
+ * Vinted API client.
792
+ *
793
+ * Provides access to all Vinted API endpoints through specialized sub-clients.
794
+ */
795
+
796
+ /**
797
+ * Vinted API client with access to all Vinted endpoints.
798
+ *
799
+ * Provides sub-clients for different resource types:
800
+ * - `search` - Search for items across Vinted marketplaces
801
+ * - `items` - Get individual item details
802
+ * - `users` - User profiles and their item listings
803
+ * - `reference` - Reference data (brands, colors, statuses, markets)
804
+ *
805
+ * @example
806
+ * ```typescript
807
+ * const client = new ScrapeBadger({ apiKey: "key" });
808
+ *
809
+ * // Search items
810
+ * const results = await client.vinted.search.search({ query: "nike air max" });
811
+ *
812
+ * // Get item details
813
+ * const item = await client.vinted.items.get(123456789);
814
+ *
815
+ * // Get user profile
816
+ * const user = await client.vinted.users.getProfile(12345);
817
+ *
818
+ * // Get reference data
819
+ * const markets = await client.vinted.reference.markets();
820
+ * ```
821
+ */
822
+ declare class VintedClient {
823
+ /** Client for item search operations */
824
+ readonly search: SearchClient$2;
825
+ /** Client for individual item operations */
826
+ readonly items: ItemsClient;
827
+ /** Client for user operations */
828
+ readonly users: UsersClient$1;
829
+ /** Client for reference data (brands, colors, statuses, markets) */
830
+ readonly reference: ReferenceClient;
831
+ /**
832
+ * Create a new Vinted client.
833
+ *
834
+ * @param client - The base HTTP client for making requests.
835
+ */
836
+ constructor(client: BaseClient);
837
+ }
838
+
839
+ /**
840
+ * TypeScript parameter types for Google Scraper API sub-clients.
841
+ *
842
+ * Response types use `Record<string, unknown>` rather than strict interfaces
843
+ * because the Google API returns rich nested data that mirrors the server-side
844
+ * Pydantic models; users can cast to their own typed shapes as needed. All
845
+ * parameter types are strictly typed.
846
+ */
847
+ type GoogleResponse = Record<string, unknown>;
848
+ interface GoogleSearchParams {
849
+ q: string;
850
+ gl?: string;
851
+ hl?: string;
852
+ num?: number;
853
+ start?: number;
854
+ domain?: string;
855
+ device?: "desktop" | "mobile";
856
+ location?: string;
857
+ lr?: string;
858
+ tbs?: string;
859
+ safe?: "off" | "medium" | "high";
860
+ uule?: string;
861
+ filter?: number;
862
+ nfpr?: number;
863
+ cr?: string;
864
+ ludocid?: string;
865
+ lsig?: string;
866
+ kgmid?: string;
867
+ si?: string;
868
+ ibp?: string;
869
+ uds?: string;
870
+ /**
871
+ * When true, chase Google's deferred AI Overview `page_token` with a
872
+ * follow-up fetch and merge the result back into `ai_overview`. Adds
873
+ * ~1s when the SERP actually defers the overview. Credit cost is
874
+ * configured per-endpoint by admins — query `/public/pricing` for the
875
+ * live rate.
876
+ */
877
+ ai_overview?: boolean;
878
+ }
879
+ interface MapsSearchParams {
880
+ /** Search query. Required unless `place_id` or `ludocid` is supplied. */
881
+ q?: string;
882
+ /** GPS coords as `@lat,lng,zoom` (e.g. `@40.745,-74.008,14z`). */
883
+ ll?: string;
884
+ gl?: string;
885
+ hl?: string;
886
+ start?: number;
887
+ /** 1-indexed page number (alternative to `start`). */
888
+ page?: number;
889
+ /** Business-type slug (e.g. `restaurant`, `hotel`). */
890
+ type?: string;
891
+ /** Raw Google Maps `pb=` override for advanced queries. */
892
+ data?: string;
893
+ /** Google Place ID (`ChIJ...`) — direct-lookup a single place. */
894
+ place_id?: string;
895
+ /** Google Location Document ID (CID) — direct-lookup by CID. */
896
+ ludocid?: string;
897
+ }
898
+ interface MapsPlaceParams {
899
+ place_id?: string;
900
+ data_id?: string;
901
+ hl?: string;
902
+ gl?: string;
903
+ }
904
+ interface MapsReviewsParams {
905
+ data_id: string;
906
+ sort_by?: "qualityScore" | "newestFirst" | "ratingHigh" | "ratingLow";
907
+ hl?: string;
908
+ next_page_token?: string;
909
+ results?: number;
910
+ }
911
+ interface MapsPhotosParams {
912
+ data_id: string;
913
+ hl?: string;
914
+ next_page_token?: string;
915
+ }
916
+ interface MapsPostsParams {
917
+ /** Google Maps data ID (`0x...:0x...`). Required unless `place_id` is set. */
918
+ data_id?: string;
919
+ /** Google Place ID — alternative to `data_id`. */
920
+ place_id?: string;
921
+ hl?: string;
922
+ gl?: string;
923
+ next_page_token?: string;
924
+ }
925
+ interface NewsSearchParams {
926
+ /** Free-text keyword query. Pass this OR one of the token fields below. */
927
+ q?: string;
928
+ hl?: string;
929
+ gl?: string;
930
+ max_results?: number;
931
+ /** Google News topic token (from a previous response's `topic_token`). */
932
+ topic_token?: string;
933
+ /** Google News publication token — scopes results to a single publisher. */
934
+ publication_token?: string;
935
+ /** Google News story token — scopes results to a single story cluster. */
936
+ story_token?: string;
937
+ }
938
+ /**
939
+ * Canonical Google News topic codes. Any string is accepted at runtime —
940
+ * use `NewsTopic` for IDE autocomplete on the standard topics and fall
941
+ * back to a plain `string` when you know the topic code out-of-band.
942
+ */
943
+ type NewsTopic = "WORLD" | "BUSINESS" | "TECHNOLOGY" | "ENTERTAINMENT" | "SPORTS" | "SCIENCE" | "HEALTH";
944
+ interface NewsTopicsParams {
945
+ topic: NewsTopic | (string & {});
946
+ hl?: string;
947
+ gl?: string;
948
+ max_results?: number;
949
+ }
950
+ interface NewsTrendingParams {
951
+ hl?: string;
952
+ gl?: string;
953
+ max_results?: number;
954
+ }
955
+ interface HotelsSearchParams {
956
+ q: string;
957
+ check_in: string;
958
+ check_out: string;
959
+ adults?: number;
960
+ currency?: string;
961
+ gl?: string;
962
+ }
963
+ interface HotelsDetailsParams {
964
+ property_token: string;
965
+ check_in: string;
966
+ check_out: string;
967
+ }
968
+ interface TrendsInterestParams {
969
+ /** Up to 5 comma-separated terms. */
970
+ q: string;
971
+ /** Geographic location code (empty = worldwide). */
972
+ geo?: string;
973
+ /** Time range — e.g. `now 1-H`, `today 12-m`, `all`, or `YYYY-MM-DD YYYY-MM-DD`. */
974
+ date?: string;
975
+ /** Category filter id (0 = all). */
976
+ category?: number;
977
+ /** Property filter — `""`, `images`, `news`, `froogle`, or `youtube`. */
978
+ gprop?: string;
979
+ }
980
+ interface TrendsRegionsParams {
981
+ q: string;
982
+ geo?: string;
983
+ date?: string;
984
+ /** Region granularity — `auto` (default), `COUNTRY`, `REGION`, `DMA`, or `CITY`. */
985
+ resolution?: "auto" | "COUNTRY" | "REGION" | "DMA" | "CITY";
986
+ }
987
+ interface TrendsRelatedParams {
988
+ q: string;
989
+ geo?: string;
990
+ date?: string;
991
+ }
992
+ interface TrendsTrendingParams {
993
+ /** Country code (ISO 3166 alpha-2). Defaults to `US`. */
994
+ geo?: string;
995
+ /** Language code (e.g. `en-US`). */
996
+ hl?: string;
997
+ /** Look-back window — Google supports `24` (default), `48`, `168` (= 1 week). */
998
+ hours?: number;
999
+ }
1000
+ type TrendsCategory = "all" | "business" | "entertainment" | "health" | "sci_tech" | "sports" | "top_stories" | "b" | "e" | "m" | "t" | "s" | "h";
1001
+ type TrendsTrendingStatus = "all" | "active";
1002
+ type TrendsTrendingSort = "relevance" | "search_volume" | "title" | "recency";
1003
+ interface TrendsTrendingNowParams {
1004
+ /** Country code (e.g. "US", "LT", "GB"). */
1005
+ geo?: string;
1006
+ /** Look-back window in hours. Common: 4, 24, 48, 168. */
1007
+ hours?: number;
1008
+ /** Category filter. */
1009
+ category?: TrendsCategory;
1010
+ /** Trend state: "all" (default) or "active" (only non-zero search volume). */
1011
+ status?: TrendsTrendingStatus;
1012
+ /** Sort order: relevance / search_volume / title / recency. */
1013
+ sort?: TrendsTrendingSort;
1014
+ /** Language code (e.g. "en-US"). */
1015
+ hl?: string;
1016
+ }
1017
+ type TrendsDataType = "TIMESERIES" | "GEO_MAP" | "GEO_MAP_0" | "RELATED_TOPICS" | "RELATED_QUERIES";
1018
+ interface TrendsSearchParams {
1019
+ /** Search term(s). Comma-separated (max 5) for TIMESERIES / GEO_MAP. */
1020
+ q: string;
1021
+ data_type?: TrendsDataType;
1022
+ geo?: string;
1023
+ date?: string;
1024
+ cat?: number;
1025
+ gprop?: string;
1026
+ region?: "COUNTRY" | "REGION" | "DMA" | "CITY";
1027
+ language?: string;
1028
+ tz?: string;
1029
+ }
1030
+ interface TrendsAutocompleteParams {
1031
+ /** Query prefix to resolve into Trends topics. */
1032
+ q: string;
1033
+ /** Language code (e.g. "en-US"). */
1034
+ hl?: string;
1035
+ /** Timezone offset in minutes. */
1036
+ tz?: string;
1037
+ }
1038
+ interface JobsSearchParams {
1039
+ q: string;
1040
+ /**
1041
+ * Data source.
1042
+ * - `"rpc"` (default, ~1-2 s): Google Careers batchexecute RPC —
1043
+ * structured JSON, scope = Google's own openings.
1044
+ * - `"serp"`: public Google Jobs SERP aggregator — 3rd-party listings
1045
+ * (LinkedIn, Indeed, Built In, ZipRecruiter, …).
1046
+ */
1047
+ mode?: "rpc" | "serp";
1048
+ location?: string;
1049
+ gl?: string;
1050
+ /** Alias for gl. */
1051
+ country?: string;
1052
+ hl?: string;
1053
+ /** Alias for hl (accepts "en-US" etc). */
1054
+ language?: string;
1055
+ /** Google domain (google.com, google.co.uk, …). */
1056
+ domain?: string;
1057
+ job_type?: "FULLTIME" | "PARTTIME" | "CONTRACTOR" | "INTERN";
1058
+ date_posted?: "today" | "3days" | "week" | "month";
1059
+ /** Work arrangement — SERP mode only. */
1060
+ ltype?: "remote" | "hybrid" | "onsite" | "work_from_home";
1061
+ /** Raw Google chip filter string — SERP mode only. */
1062
+ chips?: string;
1063
+ /** Opaque Google filter token — SERP mode only. */
1064
+ uds?: string;
1065
+ /** UULE-encoded location — SERP mode only. */
1066
+ uule?: string;
1067
+ /** Search radius in miles — SERP mode only. */
1068
+ lrad?: string;
1069
+ /** Pagination token from prior response. */
1070
+ next_page_token?: string;
1071
+ }
1072
+ interface ShoppingSearchParams {
1073
+ q: string;
1074
+ gl?: string;
1075
+ hl?: string;
1076
+ domain?: string;
1077
+ /** Zero-based page index (each page ≈ 60 tiles). */
1078
+ page?: number;
1079
+ min_price?: number;
1080
+ max_price?: number;
1081
+ sort_by?: "price_low" | "price_high" | "rating" | "reviews";
1082
+ /** Free-shipping filter. */
1083
+ free_shipping?: boolean;
1084
+ /** On-sale filter. */
1085
+ on_sale?: boolean;
1086
+ safe?: "off" | "active";
1087
+ /** `1` disables auto-correction. */
1088
+ nfpr?: number;
1089
+ /** Language restrict (e.g. `lang_en`). */
1090
+ lr?: string;
1091
+ /** Raw Google tbs filter. */
1092
+ tbs?: string;
1093
+ /** Google internal shoprs helper token. */
1094
+ shoprs?: string;
1095
+ }
1096
+ /**
1097
+ * Params for `/v1/google/shopping/product` — Google Shopping product
1098
+ * detail page lookup.
1099
+ */
1100
+ interface ShoppingProductParams {
1101
+ product_id: string;
1102
+ gl?: string;
1103
+ hl?: string;
1104
+ domain?: string;
1105
+ }
1106
+ /**
1107
+ * Params for `/v1/google/shopping/product/click` — resolve the direct
1108
+ * merchant URL for a Shopping product tile. Uses Google's "I'm Feeling
1109
+ * Lucky" redirect scoped to the card's `source` merchant via the
1110
+ * `site:` operator.
1111
+ */
1112
+ interface ShoppingClickParams {
1113
+ title: string;
1114
+ source: string;
1115
+ q: string;
1116
+ product_id?: string;
1117
+ }
1118
+ /**
1119
+ * Params for `/v1/google/patents/search`. Backed by Google Patents'
1120
+ * `/xhr/query` JSON RPC — ~1 s regardless of filter complexity.
1121
+ */
1122
+ interface PatentsSearchParams {
1123
+ /** Query string — supports Boolean logic (e.g. "quantum AND compute"). */
1124
+ q: string;
1125
+ page?: number;
1126
+ num?: number;
1127
+ sort?: "new" | "old";
1128
+ /** Comma-separated inventor names. */
1129
+ inventor?: string;
1130
+ /** Comma-separated assignee / company names. */
1131
+ assignee?: string;
1132
+ /** Patent-office country code (US, EP, WO, …). */
1133
+ country?: string;
1134
+ language?: "ENGLISH" | "GERMAN" | "CHINESE" | "FRENCH" | "JAPANESE" | "KOREAN" | "SPANISH";
1135
+ status?: "GRANT" | "APPLICATION";
1136
+ patent_type?: "PATENT" | "DESIGN";
1137
+ /** Filing/priority-date upper bound (YYYYMMDD). */
1138
+ before?: string;
1139
+ /** Filing/priority-date lower bound (YYYYMMDD). */
1140
+ after?: string;
1141
+ }
1142
+ interface PatentsDetailParams {
1143
+ /** Publication number (e.g. "US10000000B2", "EP3097156B1"). */
1144
+ patent_id: string;
1145
+ }
1146
+ interface ScholarSearchParams {
1147
+ q: string;
1148
+ hl?: string;
1149
+ as_ylo?: number;
1150
+ as_yhi?: number;
1151
+ as_sdt?: string;
1152
+ page?: number;
1153
+ num?: number;
1154
+ }
1155
+ interface ScholarProfilesParams {
1156
+ /** Author name query (e.g. "Geoffrey Hinton"). */
1157
+ mauthors: string;
1158
+ hl?: string;
1159
+ /** Next-page pagination token from a previous response. */
1160
+ after_author?: string;
1161
+ /** Previous-page pagination token. */
1162
+ before_author?: string;
1163
+ }
1164
+ interface ScholarAuthorParams {
1165
+ /** Scholar user ID (the `user` query parameter on a profile URL). */
1166
+ author_id: string;
1167
+ hl?: string;
1168
+ /** Articles pagination offset. */
1169
+ cstart?: number;
1170
+ /** Articles per page. */
1171
+ pagesize?: number;
1172
+ }
1173
+ interface ScholarAuthorCitationParams {
1174
+ author_id: string;
1175
+ hl?: string;
1176
+ }
1177
+ interface ScholarCiteParams {
1178
+ /** Cluster ID from a Scholar search result. */
1179
+ q: string;
1180
+ hl?: string;
1181
+ }
1182
+ interface AutocompleteParams {
1183
+ q: string;
1184
+ hl?: string;
1185
+ gl?: string;
1186
+ }
1187
+ interface ImagesSearchParams {
1188
+ q: string;
1189
+ gl?: string;
1190
+ hl?: string;
1191
+ /** Zero-based page index (each page ≈ 100 tiles). */
1192
+ page?: number;
1193
+ /** Max tiles to return (1-500, client-side cap). */
1194
+ results?: number;
1195
+ safe?: "off" | "active";
1196
+ /** Raw Google tbs filter (e.g. `qdr:d`). */
1197
+ tbs?: string;
1198
+ /** Size: `l`, `m`, `i`, `xXl`, `xxl`, `xxxl`. */
1199
+ imgsz?: string;
1200
+ /** Colour: `color`, `gray`, `transparent`, `red`, `orange`, … */
1201
+ imgcolor?: string;
1202
+ /** Type: `face`, `photo`, `clipart`, `lineart`, `animated`. */
1203
+ imgtype?: string;
1204
+ }
1205
+ interface VideosSearchParams {
1206
+ q: string;
1207
+ gl?: string;
1208
+ hl?: string;
1209
+ /** Zero-based page index (each page ≈ 10 tiles). */
1210
+ page?: number;
1211
+ /** Google domain (`google.com`, `google.co.uk`, …). */
1212
+ domain?: string;
1213
+ /** City-level geo-targeting. */
1214
+ location?: string;
1215
+ /** Language restrict (e.g. `lang_en`). */
1216
+ lr?: string;
1217
+ /** UULE-encoded location. */
1218
+ uule?: string;
1219
+ /** `1` disables auto-correction. */
1220
+ nfpr?: number;
1221
+ safe?: "off" | "active";
1222
+ /** Time/duration chip: `qdr:d/w/m`, `dur:s/m/l`. */
1223
+ tbs?: string;
1224
+ }
1225
+ interface FinanceQuoteParams {
1226
+ /** Ticker, optionally with exchange — `AAPL`, `AAPL:NASDAQ`, `BTC-USD`, `EURUSD`. */
1227
+ q: string;
1228
+ hl?: string;
1229
+ gl?: string;
1230
+ }
1231
+ interface AiModeSearchParams {
1232
+ q: string;
1233
+ gl?: string;
1234
+ hl?: string;
1235
+ }
1236
+ /**
1237
+ * Params for `/v1/google/lens/search`. Response carries `lens_results`
1238
+ * (Scrapingdog parity — each item has `title`, `source`,
1239
+ * `source_favicon`, `thumbnail`, optional `tag` price chip and
1240
+ * `in_stock`) plus `related_searches` chips. Legacy `results` alias
1241
+ * retained for backwards compat.
1242
+ */
1243
+ interface LensSearchParams {
1244
+ /** Public URL of the image to search visually. */
1245
+ url: string;
1246
+ /** Optional text refinement (e.g. `"pizza"`) to bias Lens. */
1247
+ query?: string;
1248
+ /** ISO country code — Scrapingdog-parity alias for `gl`. */
1249
+ country?: string;
1250
+ /** Language code — Scrapingdog-parity alias for `hl`. */
1251
+ language?: string;
1252
+ gl?: string;
1253
+ hl?: string;
1254
+ /** Bias towards shoppable product matches. */
1255
+ product?: boolean;
1256
+ /** Include the visual-matches carousel (default: true). */
1257
+ visual_matches?: boolean;
1258
+ /** Restrict to exact-match results only. */
1259
+ exact_matches?: boolean;
1260
+ }
1261
+ /**
1262
+ * Params for `/v1/google/products/detail`. Backed by Google's
1263
+ * `/async/oapv` RPC — full product payload (title, brand, price, rating,
1264
+ * specs) in ~2s via warm-session curl_cffi.
1265
+ */
1266
+ interface ProductsDetailParams {
1267
+ /** Google Shopping `gpcid`. Search results expose this on each tile. */
1268
+ product_id: string;
1269
+ /** Original search query — required, used to build the oapv context blob. */
1270
+ q: string;
1271
+ gl?: string;
1272
+ hl?: string;
1273
+ /** Google domain used to localise the SERP that yields oapv session tokens. */
1274
+ domain?: string;
1275
+ /** Extra IDs Google surfaces on Shopping tiles. Improves routing accuracy. */
1276
+ catalog_id?: string;
1277
+ image_docid?: string;
1278
+ headline_offer_docid?: string;
1279
+ mid?: string;
1280
+ /** When true, also fetches `/async/piu_ps` for the merchant offers list. */
1281
+ include_offers?: boolean;
1282
+ /** When true, also fetches `/async/toy_v` for size/colour variants. */
1283
+ include_variants?: boolean;
1284
+ /**
1285
+ * Only meaningful with `include_offers=true`. When true, browser-renders
1286
+ * the Shopping SERP so additional merchant deep URLs surface from the
1287
+ * rendered HTML. Adds ~5–8 s latency.
1288
+ */
1289
+ resolve_deep_urls?: boolean;
1290
+ }
1291
+ interface ShortsSearchParams {
1292
+ q: string;
1293
+ gl?: string;
1294
+ hl?: string;
1295
+ domain?: string;
1296
+ /** Max tiles to return (1-60 cap). */
1297
+ num?: number;
1298
+ /** Pagination offset. */
1299
+ start?: number;
1300
+ safe?: "off" | "active";
1301
+ /** `1` disables auto-correction. */
1302
+ nfpr?: number;
1303
+ /** Raw Google tbs filter (e.g. `qdr:d`). */
1304
+ tbs?: string;
1305
+ }
1306
+ type FlightsTripType = "round_trip" | "one_way" | "multi_city";
1307
+ type FlightsTravelClass = "economy" | "premium_economy" | "business" | "first";
1308
+ type FlightsStopsFilter = "any" | "nonstop" | "one_stop" | "two_stops";
1309
+ interface FlightsSearchParams {
1310
+ /** Departure airport IATA code (e.g. "JFK") or location ID. */
1311
+ departure_id: string;
1312
+ /** Arrival airport IATA code (e.g. "LHR") or location ID. */
1313
+ arrival_id: string;
1314
+ /** Outbound date in YYYY-MM-DD format. */
1315
+ outbound_date: string;
1316
+ /** Return date (required for round_trip). */
1317
+ return_date?: string;
1318
+ trip_type?: FlightsTripType;
1319
+ /** Adult passengers (1-9). */
1320
+ adults?: number;
1321
+ /** Children passengers (0-8). */
1322
+ children?: number;
1323
+ /** Infants in seat (0-4). */
1324
+ infants_in_seat?: number;
1325
+ /** Infants on lap (0-4). */
1326
+ infants_on_lap?: number;
1327
+ travel_class?: FlightsTravelClass;
1328
+ /** ISO-4217 currency code (default "USD"). */
1329
+ currency?: string;
1330
+ gl?: string;
1331
+ hl?: string;
1332
+ stops?: FlightsStopsFilter;
1333
+ /** Upper price filter. */
1334
+ max_price?: number;
1335
+ }
1336
+
1337
+ /**
1338
+ * Google AI Mode API client (udm=50 generative answers).
1339
+ */
1340
+
1341
+ /**
1342
+ * Client for Google AI Mode.
1343
+ */
1344
+ declare class AiModeClient {
1345
+ private readonly client;
1346
+ constructor(client: BaseClient);
1347
+ search(params: AiModeSearchParams): Promise<GoogleResponse>;
1348
+ }
1349
+
1350
+ /**
1351
+ * Google Autocomplete API client.
1352
+ *
1353
+ * Returns up to 10 search suggestions. Suggestions that resolve to
1354
+ * Knowledge-Graph entities (companies, people, movies, stocks, local
1355
+ * businesses, …) additionally carry `entity_name` and `thumbnail` —
1356
+ * the same enrichment Google's own search-box surfaces.
1357
+ */
1358
+
1359
+ /**
1360
+ * Client for Google Autocomplete (search suggestions).
1361
+ */
1362
+ declare class AutocompleteClient {
1363
+ private readonly client;
1364
+ constructor(client: BaseClient);
1365
+ /**
1366
+ * Get Google autocomplete suggestions for a query.
1367
+ *
1368
+ * @example
1369
+ * ```typescript
1370
+ * const res = await client.google.autocomplete.get({ q: "apple" });
1371
+ * for (const s of res.suggestions) {
1372
+ * console.log(s.value, s.entity_name, s.thumbnail);
1373
+ * }
1374
+ * ```
1375
+ */
1376
+ get(params: AutocompleteParams): Promise<GoogleResponse>;
1377
+ }
1378
+
1379
+ /**
1380
+ * Google Finance API client.
1381
+ *
1382
+ * Powered by the same `mKsvE` batchexecute RPC the Google Finance SPA
1383
+ * uses internally. Returns price / change / change% / previous_close /
1384
+ * after-hours / market hours / timezone / currency / country /
1385
+ * alternate exchange listings in ~1 s.
1386
+ */
1387
+
1388
+ /**
1389
+ * Client for Google Finance quotes.
1390
+ *
1391
+ * @example
1392
+ * ```typescript
1393
+ * const quote = await client.google.finance.quote({ q: "AAPL:NASDAQ" });
1394
+ * console.log(quote.price, quote.currency, quote.after_hours);
1395
+ * ```
1396
+ */
1397
+ declare class FinanceClient {
1398
+ private readonly client;
1399
+ constructor(client: BaseClient);
1400
+ quote(params: FinanceQuoteParams): Promise<GoogleResponse>;
1401
+ }
1402
+
1403
+ /**
1404
+ * Google Flights API client — one-way, round-trip, multi-city.
1405
+ */
1406
+
1407
+ /**
1408
+ * Client for Google Flights search.
1409
+ *
1410
+ * Supports one-way, round-trip, and multi-city itineraries with
1411
+ * passenger configuration, cabin class, stops filter, and max-price.
1412
+ * Returns Google's Best flights recommendations plus the full Other
1413
+ * flights result set, with per-offer pricing, duration, stops,
1414
+ * layovers, carbon emissions, and price insights (low / typical /
1415
+ * high + typical price range) when Google shows them.
1416
+ *
1417
+ * @example
1418
+ * ```typescript
1419
+ * const flights = await client.google.flights.search({
1420
+ * departure_id: "JFK",
1421
+ * arrival_id: "LHR",
1422
+ * outbound_date: "2026-06-15",
1423
+ * return_date: "2026-06-22",
1424
+ * adults: 2,
1425
+ * });
1426
+ * for (const offer of flights.best_flights) {
1427
+ * console.log(offer.price, offer.currency, offer.total_duration_minutes);
1428
+ * }
1429
+ * if (flights.price_insights) {
1430
+ * console.log("Price level:", flights.price_insights.price_level);
1431
+ * }
1432
+ * ```
1433
+ */
1434
+ declare class FlightsClient {
1435
+ private readonly client;
1436
+ constructor(client: BaseClient);
1437
+ /** Search Google Flights for available itineraries. */
1438
+ search(params: FlightsSearchParams): Promise<GoogleResponse>;
1439
+ }
1440
+
1441
+ /**
1442
+ * Google Hotels API client — search, property details.
1443
+ */
1444
+
1445
+ /**
1446
+ * Client for Google Hotels endpoints.
1447
+ *
1448
+ * @example
1449
+ * ```typescript
1450
+ * const hotels = await client.google.hotels.search({
1451
+ * q: "Paris",
1452
+ * check_in: "2026-05-01",
1453
+ * check_out: "2026-05-05",
1454
+ * adults: 2,
1455
+ * });
1456
+ * ```
1457
+ */
1458
+ declare class HotelsClient {
1459
+ private readonly client;
1460
+ constructor(client: BaseClient);
1461
+ search(params: HotelsSearchParams): Promise<GoogleResponse>;
1462
+ details(params: HotelsDetailsParams): Promise<GoogleResponse>;
1463
+ }
1464
+
1465
+ /**
1466
+ * Google Images API client.
1467
+ *
1468
+ * Returns up to 100 tiles per page with `title`, `source`, `link`
1469
+ * (referrer page), `thumbnail`, `image` (inline preview), `original`
1470
+ * (full-res URL), `original_width` / `original_height`,
1471
+ * `original_size` (e.g. `"635KB"`), plus licensability flags.
1472
+ */
1473
+
1474
+ /**
1475
+ * Client for Google Images search.
1476
+ *
1477
+ * @example
1478
+ * ```typescript
1479
+ * const res = await client.google.images.search({
1480
+ * q: "golden retriever",
1481
+ * imgsz: "l",
1482
+ * imgcolor: "color",
1483
+ * });
1484
+ * for (const img of res.results) {
1485
+ * console.log(img.rank, img.title, img.original);
1486
+ * }
1487
+ * ```
1488
+ */
1489
+ declare class ImagesClient {
1490
+ private readonly client;
1491
+ constructor(client: BaseClient);
1492
+ search(params: ImagesSearchParams): Promise<GoogleResponse>;
1493
+ }
1494
+
1495
+ /**
1496
+ * Google Jobs API client.
1497
+ */
1498
+
1499
+ /**
1500
+ * Client for Google Jobs search.
1501
+ *
1502
+ * @example
1503
+ * ```typescript
1504
+ * const jobs = await client.google.jobs.search({
1505
+ * q: "software engineer",
1506
+ * location: "San Francisco, CA",
1507
+ * job_type: "FULLTIME",
1508
+ * });
1509
+ * ```
1510
+ */
1511
+ declare class JobsClient {
1512
+ private readonly client;
1513
+ constructor(client: BaseClient);
1514
+ search(params: JobsSearchParams): Promise<GoogleResponse>;
1515
+ }
1516
+
1517
+ /**
1518
+ * Google Lens API client (visual image search).
1519
+ */
1520
+
1521
+ /**
1522
+ * Client for Google Lens visual search by image URL.
1523
+ *
1524
+ * Response carries `lens_results` (Scrapingdog-parity alias) with
1525
+ * `title`, `source`, `source_favicon`, `thumbnail`, optional `tag`
1526
+ * price chip and `in_stock`, plus `related_searches` chips. Legacy
1527
+ * `results` alias retained for backwards compat.
1528
+ *
1529
+ * @example
1530
+ * ```typescript
1531
+ * const out = await client.google.lens.search({
1532
+ * url: "https://example.com/photo.jpg",
1533
+ * product: true, // bias towards shoppable matches
1534
+ * });
1535
+ * for (const match of out.lens_results) {
1536
+ * console.log(match.title, match.tag);
1537
+ * }
1538
+ * ```
1539
+ */
1540
+ declare class LensClient {
1541
+ private readonly client;
1542
+ constructor(client: BaseClient);
1543
+ search(params: LensSearchParams): Promise<GoogleResponse>;
1544
+ }
1545
+
1546
+ /**
1547
+ * Google Maps API client — search, place details, reviews, photos, posts.
1548
+ */
1549
+
1550
+ /**
1551
+ * Client for Google Maps endpoints.
1552
+ *
1553
+ * @example
1554
+ * ```typescript
1555
+ * const places = await client.google.maps.search({ q: "coffee shops sf" });
1556
+ * const detail = await client.google.maps.place({ data_id: "0x...:0x..." });
1557
+ * const reviews = await client.google.maps.reviews({
1558
+ * data_id: "0x...:0x...",
1559
+ * sort_by: "newestFirst",
1560
+ * });
1561
+ * ```
1562
+ */
1563
+ declare class MapsClient {
1564
+ private readonly client;
1565
+ constructor(client: BaseClient);
1566
+ /**
1567
+ * Search Maps for places by text query, place_id, or ludocid.
1568
+ *
1569
+ * Returns up to 20 results per page with full details (place_id,
1570
+ * data_id, GPS, rating, reviews, address, phone, website, extensions,
1571
+ * weekly hours, thumbnail) in a single call.
1572
+ */
1573
+ search(params: MapsSearchParams): Promise<GoogleResponse>;
1574
+ /**
1575
+ * Get full place detail by `place_id` or `data_id`.
1576
+ *
1577
+ * Returns title, address, phone, website, GPS, rating, reviews_count,
1578
+ * rating_summary (per-star distribution), categories, extensions
1579
+ * (service_options, accessibility, offerings, payments), weekly
1580
+ * operating hours, popular_times graph, provider_id,
1581
+ * permanently_closed, thumbnail, and photo list.
1582
+ */
1583
+ place(params: MapsPlaceParams): Promise<GoogleResponse>;
1584
+ /**
1585
+ * Get reviews for a place (paginated, optional topic filter).
1586
+ *
1587
+ * Pass the `next_page_token` from `response.pagination.next` for
1588
+ * subsequent pages, or use `topic_id` from `response.topics[].id`
1589
+ * to scope to a specific review topic.
1590
+ */
1591
+ reviews(params: MapsReviewsParams): Promise<GoogleResponse>;
1592
+ /**
1593
+ * Get photos for a place with place-specific categories.
1594
+ *
1595
+ * Returns place-specific categories (Menu, Vibe, Comfort food, dish
1596
+ * names) and photo URLs from all CDN families. Use `category_id` to
1597
+ * scope to a category, or `page_size: 200` to fetch all photos in
1598
+ * one call (Google caps at ~120 photos per response).
1599
+ */
1600
+ photos(params: MapsPhotosParams): Promise<GoogleResponse>;
1601
+ /** Get business posts (promotional updates, announcements) for a place. */
1602
+ posts(params: MapsPostsParams): Promise<GoogleResponse>;
1603
+ }
1604
+
1605
+ /**
1606
+ * Google News API client — search, topics, trending.
1607
+ */
1608
+
1609
+ /**
1610
+ * Client for Google News endpoints.
1611
+ *
1612
+ * @example
1613
+ * ```typescript
1614
+ * const articles = await client.google.news.search({ q: "openai" });
1615
+ * const tech = await client.google.news.topics({ topic: "TECHNOLOGY" });
1616
+ * const trending = await client.google.news.trending();
1617
+ * ```
1618
+ */
1619
+ declare class NewsClient {
1620
+ private readonly client;
1621
+ constructor(client: BaseClient);
1622
+ /**
1623
+ * Search Google News. One of `q`, `topic_token`, `publication_token`,
1624
+ * or `story_token` is required (or pass no params for the trending
1625
+ * home feed). Returns `menu_links`, `news_results`, `related_topics`.
1626
+ */
1627
+ search(params?: NewsSearchParams): Promise<GoogleResponse>;
1628
+ topics(params: NewsTopicsParams): Promise<GoogleResponse>;
1629
+ trending(params?: NewsTrendingParams): Promise<GoogleResponse>;
1630
+ }
1631
+
1632
+ /**
1633
+ * Google Patents API client — search, detail.
1634
+ */
1635
+
1636
+ /**
1637
+ * Client for Google Patents endpoints.
1638
+ *
1639
+ * @example
1640
+ * ```typescript
1641
+ * const results = await client.google.patents.search({
1642
+ * q: "distributed lock",
1643
+ * assignee: "Google",
1644
+ * });
1645
+ * ```
1646
+ */
1647
+ declare class PatentsClient {
1648
+ private readonly client;
1649
+ constructor(client: BaseClient);
1650
+ search(params: PatentsSearchParams): Promise<GoogleResponse>;
1651
+ /**
1652
+ * Get rich patent document details by patent number.
1653
+ *
1654
+ * Response includes full abstract + every claim + complete description,
1655
+ * plus structured `cpc_classifications` (code + description), split
1656
+ * `backward_citations` / `forward_citations` (with `primary_examiner`
1657
+ * flag), `non_patent_citations`, `concepts` (research fields),
1658
+ * `legal_events` (prosecution history), `figures` (full-res URLs),
1659
+ * every `inventor`, and the full `assignees_original` history.
1660
+ */
1661
+ detail(params: PatentsDetailParams): Promise<GoogleResponse>;
1662
+ }
1663
+
1664
+ /**
1665
+ * Google Products API client (immersive product detail).
1666
+ */
1667
+
1668
+ /**
1669
+ * Client for Google's immersive product detail endpoint.
1670
+ */
1671
+ declare class ProductsClient {
1672
+ private readonly client;
1673
+ constructor(client: BaseClient);
1674
+ detail(params: ProductsDetailParams): Promise<GoogleResponse>;
1675
+ }
1676
+
1677
+ /**
1678
+ * Google Scholar API client.
1679
+ */
1680
+
1681
+ /**
1682
+ * Client for Google Scholar — search, author profiles, citation charts,
1683
+ * and citation formats.
1684
+ *
1685
+ * Search results carry doc `id`, `type` badge, wrapped `inline_links`
1686
+ * (versions + cited_by + related), PDF `resources`, and author objects
1687
+ * with `author_id` for pipe-through into {@link ScholarClient.author}.
1688
+ * The author endpoint returns structured `interests_detailed`,
1689
+ * publications with per-article `citation_id` + nested `cited_by`, and
1690
+ * lifetime + since-year citation stats.
1691
+ *
1692
+ * @example
1693
+ * ```typescript
1694
+ * const papers = await client.google.scholar.search({
1695
+ * q: "transformer neural networks",
1696
+ * as_ylo: 2020,
1697
+ * });
1698
+ * const first = papers.scholar_results[0];
1699
+ * // Pipe a profiled author into the author endpoint:
1700
+ * if (first.authors[0].author_id) {
1701
+ * const profile = await client.google.scholar.author({
1702
+ * author_id: first.authors[0].author_id,
1703
+ * });
1704
+ * }
1705
+ * ```
1706
+ */
1707
+ declare class ScholarClient {
1708
+ private readonly client;
1709
+ constructor(client: BaseClient);
1710
+ /**
1711
+ * Search Google Scholar. Returns each result with doc `id`, `type`
1712
+ * badge, wrapped `inline_links`, PDF `resources`, and structured
1713
+ * authors. Envelope includes `scholar_results` alias,
1714
+ * `related_searches`, and matched `profiles` cards.
1715
+ */
1716
+ search(params: ScholarSearchParams): Promise<GoogleResponse>;
1717
+ /** Search Google Scholar for author profiles by name. */
1718
+ profiles(params: ScholarProfilesParams): Promise<GoogleResponse>;
1719
+ /**
1720
+ * Full Scholar author profile: structured `interests_detailed`,
1721
+ * publications (with per-article `citation_id` + nested
1722
+ * `cited_by{value, link, citation_id}`), stats, and co-authors.
1723
+ */
1724
+ author(params: ScholarAuthorParams): Promise<GoogleResponse>;
1725
+ /** Citations-per-year chart for a Scholar author. */
1726
+ authorCitation(params: ScholarAuthorCitationParams): Promise<GoogleResponse>;
1727
+ /**
1728
+ * MLA / APA / Chicago / Harvard / Vancouver citation formats plus
1729
+ * BibTeX / RIS / EndNote / RefWorks export links for a paper.
1730
+ */
1731
+ cite(params: ScholarCiteParams): Promise<GoogleResponse>;
1732
+ }
1733
+
1734
+ /**
1735
+ * Google Web Search (SERP) API client.
1736
+ */
1737
+
1738
+ /**
1739
+ * Client for Google Web Search.
1740
+ *
1741
+ * @example
1742
+ * ```typescript
1743
+ * const serp = await client.google.search.search({ q: "python 3.13" });
1744
+ * for (const r of serp.organic_results as any[]) {
1745
+ * console.log(r.title, r.link);
1746
+ * }
1747
+ * ```
1748
+ */
1749
+ declare class SearchClient$1 {
1750
+ private readonly client;
1751
+ constructor(client: BaseClient);
1752
+ /**
1753
+ * Search Google and get a structured SERP response with organic results,
1754
+ * knowledge graph, People Also Ask, related searches, AI overview, and
1755
+ * pagination.
1756
+ */
1757
+ search(params: GoogleSearchParams): Promise<GoogleResponse>;
1758
+ /**
1759
+ * Lightweight Google Search — organic results + related searches only.
1760
+ *
1761
+ * ~40% faster than {@link search}. Skips ads, Knowledge Graph, AI
1762
+ * Overview, local pack, news, inline videos, and shopping blocks.
1763
+ * Credit cost is configured per-endpoint by admins — query
1764
+ * `/public/pricing` for the live rate.
1765
+ *
1766
+ * @example
1767
+ * ```typescript
1768
+ * const lite = await client.google.search.light({ q: "python 3.13" });
1769
+ * ```
1770
+ */
1771
+ light(params: GoogleSearchParams): Promise<GoogleResponse>;
1772
+ }
1773
+
1774
+ /**
1775
+ * Google Shopping API client — search and product detail.
1776
+ */
1777
+
1778
+ /**
1779
+ * Client for Google Shopping endpoints.
1780
+ *
1781
+ * Each search tile now carries Google's native `gpcid`, `catalog_id`,
1782
+ * `headline_offer_docid`, `image_docid`, and `mid`, so callers can pipe a
1783
+ * tile directly into `client.google.products.detail()` for full specs
1784
+ * plus merchant offers via the fast `/async/oapv` RPC (~2s).
1785
+ *
1786
+ * @example
1787
+ * ```typescript
1788
+ * const products = await client.google.shopping.search({ q: "laptop" });
1789
+ * const first = (products.results as any[])[0];
1790
+ * const detail = await client.google.products.detail({
1791
+ * product_id: first.gpcid,
1792
+ * q: "laptop",
1793
+ * include_offers: true, // real merchant URLs from /async/piu_ps
1794
+ * });
1795
+ * ```
1796
+ */
1797
+ declare class ShoppingClient {
1798
+ private readonly client;
1799
+ constructor(client: BaseClient);
1800
+ /** Search Google Shopping for products. */
1801
+ search(params: ShoppingSearchParams): Promise<GoogleResponse>;
1802
+ /** Fetch the Google Shopping product detail page by `product_id`. */
1803
+ product(params: ShoppingProductParams): Promise<GoogleResponse>;
1804
+ /**
1805
+ * Resolve the direct merchant URL for a Shopping product tile via
1806
+ * Google's "I'm Feeling Lucky" redirect (scoped to the card's `source`
1807
+ * merchant via the `site:` operator). You only pay for the call when
1808
+ * you actually want the merchant link — no bulk enrichment of every
1809
+ * tile.
1810
+ */
1811
+ click(params: ShoppingClickParams): Promise<GoogleResponse>;
1812
+ }
1813
+
1814
+ /**
1815
+ * Google Shorts API client — short-form vertical video results.
1816
+ */
1817
+
1818
+ /**
1819
+ * Client for Google Shorts search (`udm=39`).
1820
+ *
1821
+ * Returns a carousel of short-form videos — YouTube Shorts plus
1822
+ * TikToks, Instagram Reels, Facebook Reels, and other platforms.
1823
+ * Every tile carries `title`, `link`, `source` (platform),
1824
+ * `account_name`, `thumbnail`, `image` (inline preview),
1825
+ * `duration`, and `video_id` (YouTube only).
1826
+ *
1827
+ * @example
1828
+ * ```typescript
1829
+ * const shorts = await client.google.shorts.search({ q: "cooking hacks" });
1830
+ * for (const v of shorts.short_videos_results) {
1831
+ * console.log(v.rank, v.title, v.source, v.account_name);
1832
+ * }
1833
+ * ```
1834
+ */
1835
+ declare class ShortsClient {
1836
+ private readonly client;
1837
+ constructor(client: BaseClient);
1838
+ search(params: ShortsSearchParams): Promise<GoogleResponse>;
1839
+ }
1840
+
1841
+ /**
1842
+ * Google Trends API client — interest, regions, related, trending.
1843
+ */
1844
+
1845
+ /**
1846
+ * Client for Google Trends endpoints.
1847
+ *
1848
+ * @example
1849
+ * ```typescript
1850
+ * const interest = await client.google.trends.interest({
1851
+ * q: "python,javascript",
1852
+ * date: "today 12-m",
1853
+ * });
1854
+ * ```
1855
+ */
1856
+ declare class TrendsClient {
1857
+ private readonly client;
1858
+ constructor(client: BaseClient);
1859
+ interest(params: TrendsInterestParams): Promise<GoogleResponse>;
1860
+ regions(params: TrendsRegionsParams): Promise<GoogleResponse>;
1861
+ related(params: TrendsRelatedParams): Promise<GoogleResponse>;
1862
+ trending(params?: TrendsTrendingParams): Promise<GoogleResponse>;
1863
+ /**
1864
+ * Current trending searches with the full Google Trends UI filter set
1865
+ * — `geo`, `hours`, `category`, `status`, `sort`, `hl`.
1866
+ */
1867
+ trendingNow(params?: TrendsTrendingNowParams): Promise<GoogleResponse>;
1868
+ /**
1869
+ * Unified Google Trends query — pick the response shape via
1870
+ * `data_type` (TIMESERIES | GEO_MAP | GEO_MAP_0 | RELATED_TOPICS |
1871
+ * RELATED_QUERIES).
1872
+ */
1873
+ search(params: TrendsSearchParams): Promise<GoogleResponse>;
1874
+ /**
1875
+ * Return categorized Knowledge Graph topic entities (`mid`, `type`,
1876
+ * direct link into Trends explore) for a query prefix. Distinct from
1877
+ * Google Search autocomplete.
1878
+ */
1879
+ autocomplete(params: TrendsAutocompleteParams): Promise<GoogleResponse>;
1880
+ }
1881
+
1882
+ /**
1883
+ * Google Videos API client.
1884
+ *
1885
+ * Returns up to 10 tiles per page with `title`, `link`
1886
+ * (YouTube / Vimeo / etc.), `displayed_link`, `snippet`, `thumbnail`,
1887
+ * `image` (inline base-64), `favicon`, `duration`, `channel`,
1888
+ * `source` (platform), `date`, `video_id`, and raw `extensions`.
1889
+ */
1890
+
1891
+ /**
1892
+ * Client for Google Videos search.
1893
+ *
1894
+ * @example
1895
+ * ```typescript
1896
+ * const res = await client.google.videos.search({ q: "python tutorial" });
1897
+ * for (const v of res.results) {
1898
+ * console.log(v.rank, v.title, v.duration, v.channel);
1899
+ * }
1900
+ * ```
1901
+ */
1902
+ declare class VideosClient {
1903
+ private readonly client;
1904
+ constructor(client: BaseClient);
1905
+ search(params: VideosSearchParams): Promise<GoogleResponse>;
1906
+ }
1907
+
1908
+ /**
1909
+ * Google Scraper API aggregator — exposes all 16 Google product sub-clients.
1910
+ */
1911
+
1912
+ /**
1913
+ * Google Scraper API client with access to all 19 Google product APIs.
1914
+ *
1915
+ * @example
1916
+ * ```typescript
1917
+ * const client = new ScrapeBadger({ apiKey: "key" });
1918
+ *
1919
+ * const serp = await client.google.search.search({ q: "python 3.13" });
1920
+ * const places = await client.google.maps.search({ q: "coffee shops sf" });
1921
+ * const products = await client.google.shopping.search({ q: "laptop" });
1922
+ *
1923
+ * // Per-product merchant URL enrichment
1924
+ * const enriched = await client.google.shopping.click({
1925
+ * title: (products.results as any[])[0].title,
1926
+ * source: (products.results as any[])[0].source,
1927
+ * });
1928
+ * console.log(enriched.merchant_url);
1929
+ *
1930
+ * // New in v0.3: Shorts, Flights, and Scholar depth
1931
+ * const shorts = await client.google.shorts.search({ q: "cooking hacks" });
1932
+ * const flights = await client.google.flights.search({
1933
+ * departure_id: "JFK",
1934
+ * arrival_id: "LHR",
1935
+ * outbound_date: "2026-06-15",
1936
+ * return_date: "2026-06-22",
1937
+ * });
1938
+ * const profiles = await client.google.scholar.profiles({
1939
+ * mauthors: "Geoffrey Hinton",
1940
+ * });
1941
+ * ```
1942
+ */
1943
+ declare class GoogleClient {
1944
+ /** Google Web Search (SERP) — with optional deferred AI Overview follow-up. */
1945
+ readonly search: SearchClient$1;
1946
+ /** Google Maps — places, reviews, photos, posts. */
1947
+ readonly maps: MapsClient;
1948
+ /** Google News — articles, topics, trending. */
1949
+ readonly news: NewsClient;
1950
+ /** Google Hotels — search and property details. */
1951
+ readonly hotels: HotelsClient;
1952
+ /** Google Trends — interest, regions, related, trending, topic autocomplete. */
1953
+ readonly trends: TrendsClient;
1954
+ /** Google Jobs. */
1955
+ readonly jobs: JobsClient;
1956
+ /** Google Shopping — search, details, click enrichment. */
1957
+ readonly shopping: ShoppingClient;
1958
+ /** Google Patents — search and document details. */
1959
+ readonly patents: PatentsClient;
1960
+ /** Google Scholar — search, profiles, author, author citation, cite formats. */
1961
+ readonly scholar: ScholarClient;
1962
+ /** Google Autocomplete — search suggestions. */
1963
+ readonly autocomplete: AutocompleteClient;
1964
+ /** Google Images. */
1965
+ readonly images: ImagesClient;
1966
+ /** Google Videos. */
1967
+ readonly videos: VideosClient;
1968
+ /** Google Finance — stock and index quotes. */
1969
+ readonly finance: FinanceClient;
1970
+ /** Google AI Mode — generative answer responses. */
1971
+ readonly aiMode: AiModeClient;
1972
+ /** Google Lens — visual image search. */
1973
+ readonly lens: LensClient;
1974
+ /** Google Shorts — short-form vertical video results (udm=39). */
1975
+ readonly shorts: ShortsClient;
1976
+ /** Google Flights — one-way, round-trip, and multi-city itineraries. */
1977
+ readonly flights: FlightsClient;
1978
+ /** Google Products — immersive product detail. */
1979
+ readonly products: ProductsClient;
1980
+ constructor(client: BaseClient);
1981
+ }
1982
+
1983
+ /**
1984
+ * TypeScript types for Reddit API responses.
1985
+ *
1986
+ * This module contains all the data types used by the Reddit API client.
1987
+ */
1988
+ /**
1989
+ * A preview image with dimensions.
1990
+ */
1991
+ interface RedditPreviewImage {
1992
+ /** Image URL */
1993
+ url: string;
1994
+ /** Image width in pixels */
1995
+ width: number;
1996
+ /** Image height in pixels */
1997
+ height: number;
1998
+ }
1999
+ /**
2000
+ * Embedded media attached to a post.
2001
+ */
2002
+ interface RedditMedia {
2003
+ /** Media type identifier */
2004
+ type: string | null;
2005
+ /** Direct media URL */
2006
+ url: string | null;
2007
+ /** Thumbnail URL */
2008
+ thumbnail_url: string | null;
2009
+ /** Media width in pixels */
2010
+ width: number | null;
2011
+ /** Media height in pixels */
2012
+ height: number | null;
2013
+ }
2014
+ /**
2015
+ * An award given to a post or comment.
2016
+ */
2017
+ interface RedditAward {
2018
+ /** Award ID */
2019
+ id: string | null;
2020
+ /** Award name */
2021
+ name: string;
2022
+ /** Number of this award given */
2023
+ count: number;
2024
+ /** Award icon URL */
2025
+ icon_url: string | null;
2026
+ }
2027
+ /**
2028
+ * A Reddit post (link or self post).
2029
+ */
2030
+ interface RedditPost {
2031
+ /** Unique post identifier (without t3_ prefix) */
2032
+ id: string;
2033
+ /** Fullname with t3_ prefix */
2034
+ fullname: string;
2035
+ /** Post title */
2036
+ title: string;
2037
+ /** Self post text body */
2038
+ selftext: string;
2039
+ /** Self post text as HTML */
2040
+ selftext_html: string | null;
2041
+ /** External or self URL */
2042
+ url: string;
2043
+ /** Permalink to post on Reddit */
2044
+ permalink: string;
2045
+ /** Post domain */
2046
+ domain: string;
2047
+ /** Author username */
2048
+ author: string;
2049
+ /** Author fullname (t2_ prefixed) */
2050
+ author_fullname: string | null;
2051
+ /** Author flair text */
2052
+ author_flair_text: string | null;
2053
+ /** Author flair type (text or richtext) */
2054
+ author_flair_type: string | null;
2055
+ /** Author flair template ID */
2056
+ author_flair_template_id: string | null;
2057
+ /** Subreddit name (without r/ prefix) */
2058
+ subreddit: string;
2059
+ /** Subreddit fullname (t5_ prefixed) */
2060
+ subreddit_id: string | null;
2061
+ /** Subreddit with r/ prefix */
2062
+ subreddit_name_prefixed: string | null;
2063
+ /** Subreddit type (public, private, restricted, etc.) */
2064
+ subreddit_type: string | null;
2065
+ /** Number of subscribers in the subreddit */
2066
+ subreddit_subscribers: number | null;
2067
+ /** Post score (upvotes minus downvotes) */
2068
+ score: number;
2069
+ /** Raw upvotes */
2070
+ ups: number;
2071
+ /** Raw downvotes */
2072
+ downs: number;
2073
+ /** Upvote ratio as a decimal (e.g. 0.95) */
2074
+ upvote_ratio: number | null;
2075
+ /** Number of comments */
2076
+ num_comments: number;
2077
+ /** Number of crossposts */
2078
+ num_crossposts: number;
2079
+ /** Number of duplicate submissions */
2080
+ num_duplicates: number | null;
2081
+ /** View count (null if not available) */
2082
+ view_count: number | null;
2083
+ /** Post creation timestamp (Unix) */
2084
+ created_utc: number;
2085
+ /** Post creation time as ISO 8601 UTC string */
2086
+ created_at: string | null;
2087
+ /** Edited timestamp as float, false if not edited, or null */
2088
+ edited: number | boolean | null;
2089
+ /** Edit time as ISO 8601 UTC string (null if not edited) */
2090
+ edited_at: string | null;
2091
+ /** Whether the post is a self (text) post */
2092
+ is_self: boolean;
2093
+ /** Whether the post is a video */
2094
+ is_video: boolean;
2095
+ /** Whether the post is a gallery */
2096
+ is_gallery: boolean;
2097
+ /** Whether the post is marked NSFW */
2098
+ is_nsfw: boolean;
2099
+ /** Whether the post is marked as a spoiler */
2100
+ is_spoiler: boolean;
2101
+ /** Whether the post is locked */
2102
+ is_locked: boolean;
2103
+ /** Whether the post is stickied */
2104
+ is_stickied: boolean;
2105
+ /** Whether the post is archived */
2106
+ is_archived: boolean;
2107
+ /** Whether the post is pinned */
2108
+ is_pinned: boolean;
2109
+ /** Whether the post is original content */
2110
+ is_original_content: boolean;
2111
+ /** Whether the post is robot-indexable */
2112
+ is_robot_indexable: boolean;
2113
+ /** Whether the post is a meta post */
2114
+ is_meta: boolean;
2115
+ /** Whether the post can be crossposted */
2116
+ is_crosspostable: boolean;
2117
+ /** Whether to send reply notifications */
2118
+ send_replies: boolean;
2119
+ /** Post flair text (null if no flair) */
2120
+ link_flair_text: string | null;
2121
+ /** Post flair background color */
2122
+ link_flair_background_color: string | null;
2123
+ /** Post flair text color */
2124
+ link_flair_text_color: string | null;
2125
+ /** Post flair template ID */
2126
+ link_flair_template_id: string | null;
2127
+ /** Post flair type (text or richtext) */
2128
+ link_flair_type: string | null;
2129
+ /** Post flair CSS class */
2130
+ link_flair_css_class: string | null;
2131
+ /** Distinguished status (moderator, admin, or null) */
2132
+ distinguished: string | null;
2133
+ /** Post thumbnail URL (may be "self", "default", or "nsfw") */
2134
+ thumbnail: string | null;
2135
+ /** Thumbnail width in pixels */
2136
+ thumbnail_width: number | null;
2137
+ /** Thumbnail height in pixels */
2138
+ thumbnail_height: number | null;
2139
+ /** Post hint (image, video, link, self, etc.) */
2140
+ post_hint: string | null;
2141
+ /** Preview images */
2142
+ preview_images: RedditPreviewImage[];
2143
+ /** Embedded media metadata */
2144
+ media: RedditMedia | null;
2145
+ /** Gallery item data */
2146
+ gallery_data: Record<string, unknown>[] | null;
2147
+ /** Parent post fullname if this is a crosspost */
2148
+ crosspost_parent: string | null;
2149
+ /** Suggested sort for comments (null if default) */
2150
+ suggested_sort: string | null;
2151
+ /** Total awards received */
2152
+ total_awards: number;
2153
+ /** Award details */
2154
+ awards: RedditAward[];
2155
+ /** Number of gildings */
2156
+ gilded: number;
2157
+ /** Content categories */
2158
+ content_categories: string[] | null;
2159
+ /** Removal category (null if not removed) */
2160
+ removed_by_category: string | null;
2161
+ /** Treatment tags */
2162
+ treatment_tags: string[];
2163
+ }
2164
+ /**
2165
+ * A Reddit comment.
2166
+ */
2167
+ interface RedditComment {
2168
+ /** Unique comment identifier (without t1_ prefix) */
2169
+ id: string;
2170
+ /** Fullname with t1_ prefix */
2171
+ fullname: string;
2172
+ /** Comment body text */
2173
+ body: string;
2174
+ /** Comment body as HTML */
2175
+ body_html: string | null;
2176
+ /** Author username */
2177
+ author: string;
2178
+ /** Author fullname (t2_ prefixed) */
2179
+ author_fullname: string | null;
2180
+ /** Author flair text */
2181
+ author_flair_text: string | null;
2182
+ /** Author flair type (text or richtext) */
2183
+ author_flair_type: string | null;
2184
+ /** Subreddit name (without r/ prefix) */
2185
+ subreddit: string;
2186
+ /** Subreddit fullname (t5_ prefixed) */
2187
+ subreddit_id: string | null;
2188
+ /** Subreddit with r/ prefix */
2189
+ subreddit_name_prefixed: string | null;
2190
+ /** Subreddit type (public, private, restricted, etc.) */
2191
+ subreddit_type: string | null;
2192
+ /** Post ID this comment belongs to */
2193
+ post_id: string | null;
2194
+ /** Title of the parent post */
2195
+ post_title: string | null;
2196
+ /** Parent ID (t3_ for top-level, t1_ for reply) */
2197
+ parent_id: string | null;
2198
+ /** Permalink to comment */
2199
+ permalink: string;
2200
+ /** Comment score (upvotes minus downvotes) */
2201
+ score: number;
2202
+ /** Raw upvotes */
2203
+ ups: number;
2204
+ /** Raw downvotes */
2205
+ downs: number;
2206
+ /** Controversiality score */
2207
+ controversiality: number;
2208
+ /** Depth level (0 for top-level comments) */
2209
+ depth: number;
2210
+ /** Comment creation timestamp (Unix) */
2211
+ created_utc: number;
2212
+ /** Comment creation time as ISO 8601 UTC string */
2213
+ created_at: string | null;
2214
+ /** Edited timestamp as float, false if not edited, or null */
2215
+ edited: number | boolean | null;
2216
+ /** Edit time as ISO 8601 UTC string (null if not edited) */
2217
+ edited_at: string | null;
2218
+ /** Whether the author is the post submitter */
2219
+ is_submitter: boolean;
2220
+ /** Whether the comment is stickied */
2221
+ is_stickied: boolean;
2222
+ /** Whether the comment is locked */
2223
+ is_locked: boolean;
2224
+ /** Whether the comment score is hidden */
2225
+ is_score_hidden: boolean;
2226
+ /** Whether to send reply notifications */
2227
+ send_replies: boolean;
2228
+ /** Distinguished status (moderator, admin, or null) */
2229
+ distinguished: string | null;
2230
+ /** Total awards received */
2231
+ total_awards: number;
2232
+ /** Number of gildings */
2233
+ gilded: number;
2234
+ /** Nested replies (empty array if none) */
2235
+ replies: RedditComment[];
2236
+ }
2237
+ /**
2238
+ * A Reddit subreddit.
2239
+ */
2240
+ interface RedditSubreddit {
2241
+ /** Unique subreddit identifier */
2242
+ id: string;
2243
+ /** Fullname with t5_ prefix */
2244
+ fullname: string;
2245
+ /** Subreddit name (without r/ prefix) */
2246
+ name: string;
2247
+ /** Subreddit with r/ prefix */
2248
+ display_name_prefixed: string | null;
2249
+ /** Subreddit title */
2250
+ title: string;
2251
+ /** Full sidebar description (markdown) */
2252
+ description: string;
2253
+ /** Full sidebar description as HTML */
2254
+ description_html: string | null;
2255
+ /** Short public description */
2256
+ public_description: string;
2257
+ /** Short public description as HTML */
2258
+ public_description_html: string | null;
2259
+ /** Text shown when submitting a new post */
2260
+ submit_text: string;
2261
+ /** Submit text as HTML */
2262
+ submit_text_html: string | null;
2263
+ /** Header title text */
2264
+ header_title: string | null;
2265
+ /** Subreddit URL path */
2266
+ url: string;
2267
+ /** Subreddit type (public, private, restricted, etc.) */
2268
+ type: string;
2269
+ /** Allowed submission type (any, link, self) */
2270
+ submission_type: string | null;
2271
+ /** Number of subscribers */
2272
+ subscribers: number;
2273
+ /** Number of users currently online */
2274
+ active_users: number | null;
2275
+ /** Creation timestamp (Unix) */
2276
+ created_utc: number;
2277
+ /** Creation time as ISO 8601 UTC string */
2278
+ created_at: string | null;
2279
+ /** Whether the subreddit is marked NSFW */
2280
+ is_nsfw: boolean;
2281
+ /** Whether the subreddit is quarantined */
2282
+ is_quarantined: boolean;
2283
+ /** Whether the subreddit is advertiser-friendly */
2284
+ is_advertiser_friendly: boolean;
2285
+ /** Advertiser category */
2286
+ advertiser_category: string | null;
2287
+ /** Subreddit language code */
2288
+ language: string | null;
2289
+ /** Subreddit icon URL */
2290
+ icon_url: string | null;
2291
+ /** Header image URL */
2292
+ header_url: string | null;
2293
+ /** Banner image URL */
2294
+ banner_url: string | null;
2295
+ /** Banner background color (hex) */
2296
+ banner_background_color: string | null;
2297
+ /** Primary theme color (hex) */
2298
+ primary_color: string | null;
2299
+ /** Key theme color (hex) */
2300
+ key_color: string | null;
2301
+ /** Whether the wiki is enabled */
2302
+ wiki_enabled: boolean;
2303
+ /** Whether image posts are allowed */
2304
+ allow_images: boolean;
2305
+ /** Whether video posts are allowed */
2306
+ allow_videos: boolean;
2307
+ /** Whether gallery posts are allowed */
2308
+ allow_galleries: boolean;
2309
+ /** Whether polls are allowed */
2310
+ allow_polls: boolean;
2311
+ /** Whether the subreddit appears in discovery feeds */
2312
+ allow_discovery: boolean;
2313
+ /** Whether spoiler tags are enabled */
2314
+ spoilers_enabled: boolean;
2315
+ /** Whether custom emojis are enabled */
2316
+ emojis_enabled: boolean;
2317
+ /** Whether free-form reports are enabled */
2318
+ free_form_reports: boolean;
2319
+ /** Whether the subreddit accepts followers */
2320
+ accept_followers: boolean;
2321
+ /** Whether posting is restricted */
2322
+ restrict_posting: boolean;
2323
+ /** Whether link flairs are enabled */
2324
+ link_flair_enabled: boolean;
2325
+ /** Position of link flair (left, right, or null) */
2326
+ link_flair_position: string | null;
2327
+ /** Whether user flairs are enabled */
2328
+ user_flair_enabled: boolean;
2329
+ /** Position of user flair (left, right, or null) */
2330
+ user_flair_position: string | null;
2331
+ /** Minutes before comment scores are shown */
2332
+ comment_score_hide_mins: number;
2333
+ /** Whether posts are automatically archived */
2334
+ should_archive_posts: boolean;
2335
+ /** Media types allowed in comments */
2336
+ allowed_media_in_comments: string[];
2337
+ }
2338
+ /**
2339
+ * A Reddit user profile.
2340
+ */
2341
+ interface RedditUser {
2342
+ /** Unique user identifier */
2343
+ id: string;
2344
+ /** Fullname with t2_ prefix */
2345
+ fullname: string | null;
2346
+ /** Username (without u/ prefix) */
2347
+ name: string;
2348
+ /** Username with u/ prefix */
2349
+ display_name_prefixed: string | null;
2350
+ /** Avatar/profile icon URL */
2351
+ icon_url: string | null;
2352
+ /** Snoovatar image URL */
2353
+ snoovatar_url: string | null;
2354
+ /** Profile banner URL */
2355
+ banner_url: string | null;
2356
+ /** Profile title/tagline */
2357
+ profile_title: string | null;
2358
+ /** Profile page URL */
2359
+ profile_url: string | null;
2360
+ /** User description / about text */
2361
+ description: string;
2362
+ /** Post karma */
2363
+ link_karma: number;
2364
+ /** Comment karma */
2365
+ comment_karma: number;
2366
+ /** Karma from received awards */
2367
+ awardee_karma: number;
2368
+ /** Karma from given awards */
2369
+ awarder_karma: number;
2370
+ /** Combined total karma */
2371
+ total_karma: number;
2372
+ /** Account creation timestamp (Unix) */
2373
+ created_utc: number;
2374
+ /** Account creation time as ISO 8601 UTC string */
2375
+ created_at: string | null;
2376
+ /** Whether the account email is verified */
2377
+ has_verified_email: boolean;
2378
+ /** Whether the account is verified */
2379
+ verified: boolean;
2380
+ /** Whether the account accepts followers */
2381
+ accepts_followers: boolean;
2382
+ /** Whether the account has subscribed to Reddit */
2383
+ has_subscribed: boolean;
2384
+ /** Whether the account is a Reddit employee */
2385
+ is_employee: boolean;
2386
+ /** Whether the account is a moderator somewhere */
2387
+ is_mod: boolean;
2388
+ /** Whether the account has Reddit Premium */
2389
+ is_gold: boolean;
2390
+ /** Whether the account is suspended */
2391
+ is_suspended: boolean;
2392
+ /** Whether the profile is NSFW */
2393
+ is_nsfw: boolean;
2394
+ /** Whether the snoovatar is shown in comments */
2395
+ pref_show_snoovatar: boolean;
2396
+ }
2397
+ /**
2398
+ * A subreddit rule.
2399
+ */
2400
+ interface RedditRule {
2401
+ /** Rule priority order */
2402
+ priority: number;
2403
+ /** Short name / title of the rule */
2404
+ short_name: string;
2405
+ /** Full rule description (markdown) */
2406
+ description: string;
2407
+ /** Full rule description as HTML */
2408
+ description_html: string | null;
2409
+ /** What the rule applies to (link, comment, all) */
2410
+ kind: "link" | "comment" | "all" | string;
2411
+ /** Violation reason label */
2412
+ violation_reason: string | null;
2413
+ }
2414
+ /**
2415
+ * A subreddit wiki page.
2416
+ */
2417
+ interface RedditWikiPage {
2418
+ /** Wiki page title/slug */
2419
+ title: string;
2420
+ /** Page content (markdown) */
2421
+ content_md: string;
2422
+ /** Page content as HTML */
2423
+ content_html: string | null;
2424
+ /** Author of latest revision */
2425
+ revision_by: string | null;
2426
+ /** Revision timestamp (Unix), null if unknown */
2427
+ revision_date: number | null;
2428
+ }
2429
+ /**
2430
+ * A Reddit user trophy.
2431
+ */
2432
+ interface RedditTrophy {
2433
+ /** Trophy name */
2434
+ name: string;
2435
+ /** Trophy description */
2436
+ description: string | null;
2437
+ /** Trophy icon URL */
2438
+ icon_url: string | null;
2439
+ /** URL associated with the trophy */
2440
+ url: string | null;
2441
+ }
2442
+ /**
2443
+ * A subreddit moderator entry.
2444
+ */
2445
+ interface RedditModerator {
2446
+ /** Moderator username */
2447
+ name: string;
2448
+ /** Moderator user ID */
2449
+ id: string | null;
2450
+ /** Moderator permissions list */
2451
+ mod_permissions: string[];
2452
+ /** Date added as moderator (Unix), null if unknown */
2453
+ date: number | null;
2454
+ }
2455
+ /**
2456
+ * Pagination metadata for list responses.
2457
+ */
2458
+ interface RedditPagination {
2459
+ /** Cursor for fetching the next page (null if no more pages) */
2460
+ after: string | null;
2461
+ /** Cursor for fetching the previous page (null if on first page) */
2462
+ before: string | null;
2463
+ /** Total number of items fetched so far */
2464
+ count: number;
2465
+ /** Maximum number of items per page */
2466
+ limit: number;
2467
+ }
2468
+ /**
2469
+ * Response from the post search endpoint.
2470
+ */
2471
+ interface SearchPostsResponse {
2472
+ /** List of matching posts */
2473
+ posts: RedditPost[];
2474
+ /** Pagination metadata */
2475
+ pagination: RedditPagination;
2476
+ /** Search query string */
2477
+ query: string;
2478
+ /** Sort method used */
2479
+ sort: string;
2480
+ }
2481
+ /**
2482
+ * Response from the subreddit posts endpoint.
2483
+ */
2484
+ interface SubredditPostsResponse {
2485
+ /** List of posts in the subreddit */
2486
+ posts: RedditPost[];
2487
+ /** Pagination metadata */
2488
+ pagination: RedditPagination;
2489
+ /** Subreddit name */
2490
+ subreddit: string;
2491
+ /** Sort method used */
2492
+ sort: string;
2493
+ }
2494
+ /**
2495
+ * Response from the post detail endpoint.
2496
+ */
2497
+ interface PostDetailResponse {
2498
+ /** Full post details */
2499
+ post: RedditPost;
2500
+ }
2501
+ /**
2502
+ * Response from the post comments endpoint.
2503
+ */
2504
+ interface PostCommentsResponse {
2505
+ /** Post details */
2506
+ post: RedditPost;
2507
+ /** Top-level comments with nested replies */
2508
+ comments: RedditComment[];
2509
+ /** Pagination metadata */
2510
+ pagination: RedditPagination;
2511
+ }
2512
+ /**
2513
+ * Response from the post duplicates endpoint.
2514
+ */
2515
+ interface PostDuplicatesResponse {
2516
+ /** The original post */
2517
+ original: RedditPost;
2518
+ /** Cross-posts and duplicate submissions */
2519
+ duplicates: RedditPost[];
2520
+ /** Pagination metadata */
2521
+ pagination: RedditPagination;
2522
+ }
2523
+ /**
2524
+ * Response from the subreddit detail endpoint.
2525
+ */
2526
+ interface SubredditDetailResponse {
2527
+ /** Full subreddit details */
2528
+ subreddit: RedditSubreddit;
2529
+ }
2530
+ /**
2531
+ * Response from the subreddit rules endpoint.
2532
+ */
2533
+ interface SubredditRulesResponse {
2534
+ /** List of subreddit rules */
2535
+ rules: RedditRule[];
2536
+ /** Subreddit name */
2537
+ subreddit: string;
2538
+ }
2539
+ /**
2540
+ * Response from the subreddit moderators endpoint.
2541
+ */
2542
+ interface SubredditModeratorsResponse {
2543
+ /** List of moderators */
2544
+ moderators: RedditModerator[];
2545
+ /** Subreddit name */
2546
+ subreddit: string;
2547
+ }
2548
+ /**
2549
+ * Response from the subreddit wiki pages list endpoint.
2550
+ */
2551
+ interface SubredditWikiPagesResponse {
2552
+ /** List of wiki page slugs */
2553
+ pages: string[];
2554
+ /** Subreddit name */
2555
+ subreddit: string;
2556
+ }
2557
+ /**
2558
+ * Response from the wiki page endpoint.
2559
+ */
2560
+ interface WikiPageResponse {
2561
+ /** The wiki page content */
2562
+ page: RedditWikiPage;
2563
+ /** Subreddit name */
2564
+ subreddit: string;
2565
+ }
2566
+ /**
2567
+ * Response from the user profile endpoint.
2568
+ */
2569
+ interface UserProfileResponse {
2570
+ /** Full user profile */
2571
+ user: RedditUser;
2572
+ }
2573
+ /**
2574
+ * Response from the user posts endpoint.
2575
+ */
2576
+ interface UserPostsResponse {
2577
+ /** List of user's posts */
2578
+ posts: RedditPost[];
2579
+ /** Pagination metadata */
2580
+ pagination: RedditPagination;
2581
+ /** Username */
2582
+ username: string;
2583
+ }
2584
+ /**
2585
+ * Response from the user comments endpoint.
2586
+ */
2587
+ interface UserCommentsResponse {
2588
+ /** List of user's comments */
2589
+ comments: RedditComment[];
2590
+ /** Pagination metadata */
2591
+ pagination: RedditPagination;
2592
+ /** Username */
2593
+ username: string;
2594
+ }
2595
+ /**
2596
+ * Response from the user moderated subreddits endpoint.
2597
+ */
2598
+ interface UserModeratedResponse {
2599
+ /** Subreddits moderated by the user */
2600
+ subreddits: RedditSubreddit[];
2601
+ /** Username */
2602
+ username: string;
2603
+ }
2604
+ /**
2605
+ * Response from the user trophies endpoint.
2606
+ */
2607
+ interface UserTrophiesResponse {
2608
+ /** List of trophies awarded to the user */
2609
+ trophies: RedditTrophy[];
2610
+ /** Username */
2611
+ username: string;
2612
+ }
2613
+ /**
2614
+ * Response from the subreddit search endpoint.
2615
+ */
2616
+ interface SearchSubredditsResponse {
2617
+ /** List of matching subreddits */
2618
+ subreddits: RedditSubreddit[];
2619
+ /** Pagination metadata */
2620
+ pagination: RedditPagination;
2621
+ /** Search query string */
2622
+ query: string;
2623
+ }
2624
+ /**
2625
+ * Response from the user search endpoint.
2626
+ */
2627
+ interface SearchUsersResponse {
2628
+ /** List of matching users */
2629
+ users: RedditUser[];
2630
+ /** Pagination metadata */
2631
+ pagination: RedditPagination;
2632
+ /** Search query string */
2633
+ query: string;
2634
+ }
2635
+ /**
2636
+ * Response from the trending posts endpoint.
2637
+ */
2638
+ interface TrendingPostsResponse {
2639
+ /** List of trending posts */
2640
+ posts: RedditPost[];
2641
+ /** Pagination metadata */
2642
+ pagination: RedditPagination;
2643
+ /** Sort method used */
2644
+ sort: string;
2645
+ }
2646
+ /**
2647
+ * Response from the popular subreddits endpoint.
2648
+ */
2649
+ interface PopularSubredditsResponse {
2650
+ /** List of popular subreddits */
2651
+ subreddits: RedditSubreddit[];
2652
+ /** Pagination metadata */
2653
+ pagination: RedditPagination;
2654
+ }
2655
+ /**
2656
+ * Response from the domain posts endpoint.
2657
+ */
2658
+ interface DomainPostsResponse {
2659
+ /** List of posts linking to the domain */
2660
+ posts: RedditPost[];
2661
+ /** Pagination metadata */
2662
+ pagination: RedditPagination;
2663
+ /** Domain name */
2664
+ domain: string;
2665
+ }
2666
+
2667
+ /**
2668
+ * Reddit Search API client.
2669
+ *
2670
+ * Provides methods for searching Reddit posts, subreddits, users, and domain posts.
2671
+ */
2672
+
2673
+ /**
2674
+ * Client for Reddit search endpoints.
2675
+ *
2676
+ * @example
2677
+ * ```typescript
2678
+ * const client = new ScrapeBadger({ apiKey: "key" });
2679
+ *
2680
+ * // Search posts
2681
+ * const results = await client.reddit.search.posts({ query: "typescript tips" });
2682
+ * for (const post of results.posts) {
2683
+ * console.log(`${post.title} — ${post.score} points`);
2684
+ * }
2685
+ *
2686
+ * // Search subreddits
2687
+ * const subs = await client.reddit.search.subreddits({ query: "programming" });
2688
+ *
2689
+ * // Get posts from a domain
2690
+ * const domainPosts = await client.reddit.search.domainPosts({ domain: "github.com" });
2691
+ * ```
2692
+ */
2693
+ declare class SearchClient {
2694
+ private readonly client;
2695
+ constructor(client: BaseClient);
2696
+ /**
2697
+ * Search Reddit posts.
2698
+ *
2699
+ * @param options - Search parameters.
2700
+ * @param options.query - Search query string.
2701
+ * @param options.subreddit - Restrict search to a specific subreddit.
2702
+ * @param options.sort - Sort order (relevance, hot, top, new, comments).
2703
+ * @param options.time - Time filter (hour, day, week, month, year, all).
2704
+ * @param options.after - Pagination cursor for the next page.
2705
+ * @param options.limit - Number of results to return (max 100).
2706
+ * @returns Search results with posts and pagination metadata.
2707
+ * @throws AuthenticationError - If the API key is invalid.
2708
+ * @throws ValidationError - If the search parameters are invalid.
2709
+ *
2710
+ * @example
2711
+ * ```typescript
2712
+ * const results = await client.reddit.search.posts({
2713
+ * query: "best practices",
2714
+ * subreddit: "programming",
2715
+ * sort: "top",
2716
+ * time: "month",
2717
+ * limit: 25,
2718
+ * });
2719
+ * console.log(`Found ${results.posts.length} posts`);
2720
+ * ```
2721
+ */
2722
+ posts(options: {
2723
+ query: string;
2724
+ subreddit?: string;
2725
+ sort?: "relevance" | "hot" | "top" | "new" | "comments";
2726
+ time?: "hour" | "day" | "week" | "month" | "year" | "all";
2727
+ after?: string;
2728
+ limit?: number;
2729
+ }): Promise<SearchPostsResponse>;
2730
+ /**
2731
+ * Search Reddit subreddits.
2732
+ *
2733
+ * @param options - Search parameters.
2734
+ * @param options.query - Search query string.
2735
+ * @param options.after - Pagination cursor for the next page.
2736
+ * @param options.limit - Number of results to return (max 100).
2737
+ * @returns Matching subreddits with pagination metadata.
2738
+ * @throws AuthenticationError - If the API key is invalid.
2739
+ * @throws ValidationError - If the search parameters are invalid.
2740
+ *
2741
+ * @example
2742
+ * ```typescript
2743
+ * const results = await client.reddit.search.subreddits({
2744
+ * query: "javascript",
2745
+ * limit: 10,
2746
+ * });
2747
+ * for (const sub of results.subreddits) {
2748
+ * console.log(`r/${sub.display_name}: ${sub.subscribers.toLocaleString()} subscribers`);
2749
+ * }
2750
+ * ```
2751
+ */
2752
+ subreddits(options: {
2753
+ query: string;
2754
+ after?: string;
2755
+ limit?: number;
2756
+ }): Promise<SearchSubredditsResponse>;
2757
+ /**
2758
+ * Search Reddit users.
2759
+ *
2760
+ * @param options - Search parameters.
2761
+ * @param options.query - Search query string.
2762
+ * @param options.after - Pagination cursor for the next page.
2763
+ * @param options.limit - Number of results to return (max 100).
2764
+ * @returns Matching users with pagination metadata.
2765
+ * @throws AuthenticationError - If the API key is invalid.
2766
+ * @throws ValidationError - If the search parameters are invalid.
2767
+ *
2768
+ * @example
2769
+ * ```typescript
2770
+ * const results = await client.reddit.search.users({
2771
+ * query: "john",
2772
+ * limit: 20,
2773
+ * });
2774
+ * for (const user of results.users) {
2775
+ * console.log(`u/${user.name}: ${user.total_karma.toLocaleString()} karma`);
2776
+ * }
2777
+ * ```
2778
+ */
2779
+ users(options: {
2780
+ query: string;
2781
+ after?: string;
2782
+ limit?: number;
2783
+ }): Promise<SearchUsersResponse>;
2784
+ /**
2785
+ * Get Reddit posts linking to a specific domain.
2786
+ *
2787
+ * @param options - Request parameters.
2788
+ * @param options.domain - Domain name to search for (e.g. "github.com").
2789
+ * @param options.sort - Sort order (hot, new, top, rising).
2790
+ * @param options.time - Time filter for top sort (hour, day, week, month, year, all).
2791
+ * @param options.after - Pagination cursor for the next page.
2792
+ * @param options.limit - Number of results to return (max 100).
2793
+ * @returns Posts linking to the domain with pagination metadata.
2794
+ * @throws AuthenticationError - If the API key is invalid.
2795
+ * @throws ValidationError - If the parameters are invalid.
2796
+ *
2797
+ * @example
2798
+ * ```typescript
2799
+ * const results = await client.reddit.search.domainPosts({
2800
+ * domain: "github.com",
2801
+ * sort: "top",
2802
+ * time: "week",
2803
+ * limit: 25,
2804
+ * });
2805
+ * for (const post of results.posts) {
2806
+ * console.log(`r/${post.subreddit}: ${post.title}`);
2807
+ * }
2808
+ * ```
2809
+ */
2810
+ domainPosts(options: {
2811
+ domain: string;
2812
+ sort?: "hot" | "new" | "top" | "rising";
2813
+ time?: "hour" | "day" | "week" | "month" | "year" | "all";
2814
+ after?: string;
2815
+ limit?: number;
2816
+ }): Promise<DomainPostsResponse>;
2817
+ }
2818
+
2819
+ /**
2820
+ * Reddit Posts API client.
2821
+ *
2822
+ * Provides methods for fetching trending posts, post details, comments, and duplicates.
2823
+ */
2824
+
2825
+ /**
2826
+ * Client for Reddit post endpoints.
2827
+ *
2828
+ * @example
2829
+ * ```typescript
2830
+ * const client = new ScrapeBadger({ apiKey: "key" });
2831
+ *
2832
+ * // Get trending posts
2833
+ * const trending = await client.reddit.posts.trending({ subreddit: "programming" });
2834
+ *
2835
+ * // Get post details
2836
+ * const post = await client.reddit.posts.get("t3_abc123");
2837
+ *
2838
+ * // Get post comments
2839
+ * const { comments } = await client.reddit.posts.comments("abc123", { subreddit: "programming" });
2840
+ * ```
2841
+ */
2842
+ declare class PostsClient {
2843
+ private readonly client;
2844
+ constructor(client: BaseClient);
2845
+ /**
2846
+ * Get trending/hot posts from Reddit or a specific subreddit.
2847
+ *
2848
+ * @param options - Request parameters.
2849
+ * @param options.subreddit - Subreddit name (without r/). If omitted, returns site-wide posts.
2850
+ * @param options.sort - Sort order (hot, new, top, rising, controversial).
2851
+ * @param options.time - Time filter for top/controversial (hour, day, week, month, year, all).
2852
+ * @param options.after - Pagination cursor for the next page.
2853
+ * @param options.limit - Number of results to return (max 100).
2854
+ * @returns Trending posts with pagination metadata.
2855
+ * @throws AuthenticationError - If the API key is invalid.
2856
+ *
2857
+ * @example
2858
+ * ```typescript
2859
+ * const results = await client.reddit.posts.trending({
2860
+ * subreddit: "worldnews",
2861
+ * sort: "hot",
2862
+ * limit: 25,
2863
+ * });
2864
+ * for (const post of results.posts) {
2865
+ * console.log(`${post.title} (${post.num_comments} comments)`);
2866
+ * }
2867
+ * ```
2868
+ */
2869
+ trending(options?: {
2870
+ subreddit?: string;
2871
+ sort?: "hot" | "new" | "top" | "rising" | "controversial";
2872
+ time?: "hour" | "day" | "week" | "month" | "year" | "all";
2873
+ after?: string;
2874
+ limit?: number;
2875
+ }): Promise<TrendingPostsResponse>;
2876
+ /**
2877
+ * Get full details of a single Reddit post.
2878
+ *
2879
+ * @param postId - The Reddit post ID (e.g. "abc123" or "t3_abc123").
2880
+ * @param options - Optional parameters.
2881
+ * @param options.subreddit - Subreddit name (helps resolve the post URL).
2882
+ * @returns Full post details.
2883
+ * @throws NotFoundError - If the post doesn't exist.
2884
+ * @throws AuthenticationError - If the API key is invalid.
2885
+ *
2886
+ * @example
2887
+ * ```typescript
2888
+ * const response = await client.reddit.posts.get("abc123", { subreddit: "programming" });
2889
+ * const { post } = response;
2890
+ * console.log(`${post.title} by u/${post.author}`);
2891
+ * console.log(`Score: ${post.score}, Comments: ${post.num_comments}`);
2892
+ * ```
2893
+ */
2894
+ get(postId: string, options?: {
2895
+ subreddit?: string;
2896
+ }): Promise<PostDetailResponse>;
2897
+ /**
2898
+ * Get comments for a Reddit post.
2899
+ *
2900
+ * @param postId - The Reddit post ID (e.g. "abc123" or "t3_abc123").
2901
+ * @param options - Optional parameters.
2902
+ * @param options.subreddit - Subreddit name (helps resolve the post URL).
2903
+ * @param options.sort - Comment sort order (confidence, top, new, controversial, old, qa).
2904
+ * @param options.depth - Maximum comment tree depth.
2905
+ * @param options.limit - Number of top-level comments to return.
2906
+ * @returns Post details and nested comment tree.
2907
+ * @throws NotFoundError - If the post doesn't exist.
2908
+ * @throws AuthenticationError - If the API key is invalid.
2909
+ *
2910
+ * @example
2911
+ * ```typescript
2912
+ * const response = await client.reddit.posts.comments("abc123", {
2913
+ * subreddit: "programming",
2914
+ * sort: "top",
2915
+ * limit: 50,
2916
+ * });
2917
+ * for (const comment of response.comments) {
2918
+ * console.log(`u/${comment.author}: ${comment.body.slice(0, 100)}`);
2919
+ * }
2920
+ * ```
2921
+ */
2922
+ comments(postId: string, options?: {
2923
+ subreddit?: string;
2924
+ sort?: "confidence" | "top" | "new" | "controversial" | "old" | "qa";
2925
+ depth?: number;
2926
+ limit?: number;
2927
+ }): Promise<PostCommentsResponse>;
2928
+ /**
2929
+ * Get cross-posts and duplicate submissions of a Reddit post.
2930
+ *
2931
+ * @param postId - The Reddit post ID (e.g. "abc123" or "t3_abc123").
2932
+ * @param options - Optional parameters.
2933
+ * @param options.after - Pagination cursor for the next page.
2934
+ * @param options.limit - Number of results to return (max 100).
2935
+ * @returns The original post and its duplicate submissions.
2936
+ * @throws NotFoundError - If the post doesn't exist.
2937
+ * @throws AuthenticationError - If the API key is invalid.
2938
+ *
2939
+ * @example
2940
+ * ```typescript
2941
+ * const response = await client.reddit.posts.duplicates("abc123");
2942
+ * console.log(`Original: ${response.post.title}`);
2943
+ * console.log(`Cross-posted ${response.duplicates.length} times`);
2944
+ * for (const dupe of response.duplicates) {
2945
+ * console.log(` r/${dupe.subreddit}: ${dupe.score} points`);
2946
+ * }
2947
+ * ```
2948
+ */
2949
+ duplicates(postId: string, options?: {
2950
+ after?: string;
2951
+ limit?: number;
2952
+ }): Promise<PostDuplicatesResponse>;
2953
+ }
2954
+
2955
+ /**
2956
+ * Reddit Subreddits API client.
2957
+ *
2958
+ * Provides methods for fetching subreddit details, posts, rules, moderators, and wiki pages.
2959
+ */
2960
+
2961
+ /**
2962
+ * Client for Reddit subreddit endpoints.
2963
+ *
2964
+ * @example
2965
+ * ```typescript
2966
+ * const client = new ScrapeBadger({ apiKey: "key" });
2967
+ *
2968
+ * // Get subreddit details
2969
+ * const sub = await client.reddit.subreddits.get("programming");
2970
+ * console.log(`r/programming: ${sub.subreddit.subscribers.toLocaleString()} subscribers`);
2971
+ *
2972
+ * // Get subreddit posts
2973
+ * const posts = await client.reddit.subreddits.posts("programming", { sort: "top" });
2974
+ *
2975
+ * // Get subreddit rules
2976
+ * const rules = await client.reddit.subreddits.rules("programming");
2977
+ * ```
2978
+ */
2979
+ declare class SubredditsClient {
2980
+ private readonly client;
2981
+ constructor(client: BaseClient);
2982
+ /**
2983
+ * Get a subreddit's full details and metadata.
2984
+ *
2985
+ * @param subreddit - Subreddit name (without r/ prefix).
2986
+ * @returns Full subreddit details.
2987
+ * @throws NotFoundError - If the subreddit doesn't exist.
2988
+ * @throws AuthenticationError - If the API key is invalid.
2989
+ *
2990
+ * @example
2991
+ * ```typescript
2992
+ * const response = await client.reddit.subreddits.get("javascript");
2993
+ * const { subreddit } = response;
2994
+ * console.log(`${subreddit.title}: ${subreddit.subscribers.toLocaleString()} members`);
2995
+ * console.log(`Description: ${subreddit.public_description}`);
2996
+ * ```
2997
+ */
2998
+ get(subreddit: string): Promise<SubredditDetailResponse>;
2999
+ /**
3000
+ * Get posts from a subreddit.
3001
+ *
3002
+ * @param subreddit - Subreddit name (without r/ prefix).
3003
+ * @param options - Optional parameters.
3004
+ * @param options.sort - Sort order (hot, new, top, rising, controversial).
3005
+ * @param options.time - Time filter for top/controversial (hour, day, week, month, year, all).
3006
+ * @param options.after - Pagination cursor for the next page.
3007
+ * @param options.limit - Number of results to return (max 100).
3008
+ * @returns Subreddit posts with pagination metadata.
3009
+ * @throws NotFoundError - If the subreddit doesn't exist.
3010
+ * @throws AuthenticationError - If the API key is invalid.
3011
+ *
3012
+ * @example
3013
+ * ```typescript
3014
+ * const response = await client.reddit.subreddits.posts("typescript", {
3015
+ * sort: "top",
3016
+ * time: "week",
3017
+ * limit: 25,
3018
+ * });
3019
+ * for (const post of response.posts) {
3020
+ * console.log(`${post.title} — ${post.score} pts`);
3021
+ * }
3022
+ * ```
3023
+ */
3024
+ posts(subreddit: string, options?: {
3025
+ sort?: "hot" | "new" | "top" | "rising" | "controversial";
3026
+ time?: "hour" | "day" | "week" | "month" | "year" | "all";
3027
+ after?: string;
3028
+ limit?: number;
3029
+ }): Promise<SubredditPostsResponse>;
3030
+ /**
3031
+ * Get the rules for a subreddit.
3032
+ *
3033
+ * @param subreddit - Subreddit name (without r/ prefix).
3034
+ * @returns List of subreddit rules.
3035
+ * @throws NotFoundError - If the subreddit doesn't exist.
3036
+ * @throws AuthenticationError - If the API key is invalid.
3037
+ *
3038
+ * @example
3039
+ * ```typescript
3040
+ * const response = await client.reddit.subreddits.rules("AskReddit");
3041
+ * for (const rule of response.rules) {
3042
+ * console.log(`${rule.priority}. ${rule.short_name}`);
3043
+ * console.log(` ${rule.description}`);
3044
+ * }
3045
+ * ```
3046
+ */
3047
+ rules(subreddit: string): Promise<SubredditRulesResponse>;
3048
+ /**
3049
+ * Get the moderators of a subreddit.
3050
+ *
3051
+ * @param subreddit - Subreddit name (without r/ prefix).
3052
+ * @param options - Optional parameters.
3053
+ * @param options.after - Pagination cursor for the next page.
3054
+ * @param options.limit - Number of results to return.
3055
+ * @returns List of moderators with pagination metadata.
3056
+ * @throws NotFoundError - If the subreddit doesn't exist.
3057
+ * @throws AuthenticationError - If the API key is invalid.
3058
+ *
3059
+ * @example
3060
+ * ```typescript
3061
+ * const response = await client.reddit.subreddits.moderators("programming");
3062
+ * for (const mod of response.moderators) {
3063
+ * console.log(`u/${mod.name}: [${mod.mod_permissions.join(", ")}]`);
3064
+ * }
3065
+ * ```
3066
+ */
3067
+ moderators(subreddit: string, options?: {
3068
+ after?: string;
3069
+ limit?: number;
3070
+ }): Promise<SubredditModeratorsResponse>;
3071
+ /**
3072
+ * List all wiki pages in a subreddit.
3073
+ *
3074
+ * @param subreddit - Subreddit name (without r/ prefix).
3075
+ * @returns List of wiki page slugs.
3076
+ * @throws NotFoundError - If the subreddit doesn't exist.
3077
+ * @throws AuthenticationError - If the API key is invalid.
3078
+ *
3079
+ * @example
3080
+ * ```typescript
3081
+ * const response = await client.reddit.subreddits.wikiPages("rust");
3082
+ * for (const page of response.pages) {
3083
+ * console.log(`/r/rust/wiki/${page}`);
3084
+ * }
3085
+ * ```
3086
+ */
3087
+ wikiPages(subreddit: string): Promise<SubredditWikiPagesResponse>;
3088
+ /**
3089
+ * Get the content of a specific wiki page in a subreddit.
3090
+ *
3091
+ * @param subreddit - Subreddit name (without r/ prefix).
3092
+ * @param page - Wiki page slug (e.g. "index", "faq").
3093
+ * @returns Wiki page content and metadata.
3094
+ * @throws NotFoundError - If the subreddit or wiki page doesn't exist.
3095
+ * @throws AuthenticationError - If the API key is invalid.
3096
+ *
3097
+ * @example
3098
+ * ```typescript
3099
+ * const response = await client.reddit.subreddits.wikiPage("learnprogramming", "faq");
3100
+ * console.log(`Last edited by: u/${response.page.revision_by}`);
3101
+ * console.log(response.page.content_md);
3102
+ * ```
3103
+ */
3104
+ wikiPage(subreddit: string, page: string): Promise<WikiPageResponse>;
3105
+ /**
3106
+ * Get the most popular subreddits on Reddit.
3107
+ *
3108
+ * @param options - Optional parameters.
3109
+ * @param options.after - Pagination cursor for the next page.
3110
+ * @param options.limit - Number of results to return (max 100).
3111
+ * @returns Popular subreddits with pagination metadata.
3112
+ * @throws AuthenticationError - If the API key is invalid.
3113
+ *
3114
+ * @example
3115
+ * ```typescript
3116
+ * const response = await client.reddit.subreddits.popular({ limit: 20 });
3117
+ * for (const sub of response.subreddits) {
3118
+ * console.log(`r/${sub.display_name}: ${sub.subscribers.toLocaleString()} subscribers`);
3119
+ * }
3120
+ * ```
3121
+ */
3122
+ popular(options?: {
3123
+ after?: string;
3124
+ limit?: number;
3125
+ }): Promise<PopularSubredditsResponse>;
3126
+ /**
3127
+ * Get newly created subreddits on Reddit.
3128
+ *
3129
+ * @param options - Optional parameters.
3130
+ * @param options.after - Pagination cursor for the next page.
3131
+ * @param options.limit - Number of results to return (max 100).
3132
+ * @returns New subreddits with pagination metadata.
3133
+ * @throws AuthenticationError - If the API key is invalid.
3134
+ *
3135
+ * @example
3136
+ * ```typescript
3137
+ * const response = await client.reddit.subreddits.newSubreddits({ limit: 20 });
3138
+ * for (const sub of response.subreddits) {
3139
+ * console.log(`r/${sub.display_name} (created: ${new Date(sub.created_utc * 1000).toLocaleDateString()})`);
3140
+ * }
3141
+ * ```
3142
+ */
3143
+ newSubreddits(options?: {
3144
+ after?: string;
3145
+ limit?: number;
3146
+ }): Promise<PopularSubredditsResponse>;
3147
+ }
3148
+
3149
+ /**
3150
+ * Reddit Users API client.
3151
+ *
3152
+ * Provides methods for fetching Reddit user profiles, posts, comments, moderated subreddits, and trophies.
3153
+ */
3154
+
3155
+ /**
3156
+ * Client for Reddit user endpoints.
3157
+ *
3158
+ * @example
3159
+ * ```typescript
3160
+ * const client = new ScrapeBadger({ apiKey: "key" });
3161
+ *
3162
+ * // Get user profile
3163
+ * const profile = await client.reddit.users.get("spez");
3164
+ * console.log(`u/${profile.user.name}: ${profile.user.total_karma.toLocaleString()} karma`);
3165
+ *
3166
+ * // Get user's recent posts
3167
+ * const posts = await client.reddit.users.posts("spez", { sort: "top", limit: 10 });
3168
+ *
3169
+ * // Get user's comments
3170
+ * const comments = await client.reddit.users.comments("spez", { sort: "new" });
3171
+ * ```
3172
+ */
3173
+ declare class UsersClient {
3174
+ private readonly client;
3175
+ constructor(client: BaseClient);
3176
+ /**
3177
+ * Get a Reddit user's profile.
3178
+ *
3179
+ * @param username - The Reddit username (without u/ prefix).
3180
+ * @returns The user profile response.
3181
+ * @throws NotFoundError - If the user doesn't exist or is suspended.
3182
+ * @throws AuthenticationError - If the API key is invalid.
3183
+ *
3184
+ * @example
3185
+ * ```typescript
3186
+ * const response = await client.reddit.users.get("spez");
3187
+ * const { user } = response;
3188
+ * console.log(`u/${user.name}`);
3189
+ * console.log(`Karma: ${user.total_karma.toLocaleString()} (${user.link_karma} post, ${user.comment_karma} comment)`);
3190
+ * console.log(`Account age: ${new Date(user.created_utc * 1000).toLocaleDateString()}`);
3191
+ * ```
3192
+ */
3193
+ get(username: string): Promise<UserProfileResponse>;
3194
+ /**
3195
+ * Get posts submitted by a Reddit user.
3196
+ *
3197
+ * @param username - The Reddit username (without u/ prefix).
3198
+ * @param options - Optional parameters.
3199
+ * @param options.sort - Sort order (hot, new, top, controversial).
3200
+ * @param options.time - Time filter for top/controversial (hour, day, week, month, year, all).
3201
+ * @param options.after - Pagination cursor for the next page.
3202
+ * @param options.limit - Number of results to return (max 100).
3203
+ * @returns The user's posts with pagination metadata.
3204
+ * @throws NotFoundError - If the user doesn't exist.
3205
+ * @throws AuthenticationError - If the API key is invalid.
3206
+ *
3207
+ * @example
3208
+ * ```typescript
3209
+ * const response = await client.reddit.users.posts("spez", {
3210
+ * sort: "top",
3211
+ * time: "all",
3212
+ * limit: 25,
3213
+ * });
3214
+ * for (const post of response.posts) {
3215
+ * console.log(`r/${post.subreddit}: ${post.title} (${post.score} pts)`);
3216
+ * }
3217
+ * ```
3218
+ */
3219
+ posts(username: string, options?: {
3220
+ sort?: "hot" | "new" | "top" | "controversial";
3221
+ time?: "hour" | "day" | "week" | "month" | "year" | "all";
3222
+ after?: string;
3223
+ limit?: number;
3224
+ }): Promise<UserPostsResponse>;
3225
+ /**
3226
+ * Get comments made by a Reddit user.
3227
+ *
3228
+ * @param username - The Reddit username (without u/ prefix).
3229
+ * @param options - Optional parameters.
3230
+ * @param options.sort - Sort order (hot, new, top, controversial).
3231
+ * @param options.time - Time filter for top/controversial (hour, day, week, month, year, all).
3232
+ * @param options.after - Pagination cursor for the next page.
3233
+ * @param options.limit - Number of results to return (max 100).
3234
+ * @returns The user's comments with pagination metadata.
3235
+ * @throws NotFoundError - If the user doesn't exist.
3236
+ * @throws AuthenticationError - If the API key is invalid.
3237
+ *
3238
+ * @example
3239
+ * ```typescript
3240
+ * const response = await client.reddit.users.comments("spez", {
3241
+ * sort: "new",
3242
+ * limit: 50,
3243
+ * });
3244
+ * for (const comment of response.comments) {
3245
+ * console.log(`r/${comment.subreddit}: ${comment.body.slice(0, 80)}`);
3246
+ * }
3247
+ * ```
3248
+ */
3249
+ comments(username: string, options?: {
3250
+ sort?: "hot" | "new" | "top" | "controversial";
3251
+ time?: "hour" | "day" | "week" | "month" | "year" | "all";
3252
+ after?: string;
3253
+ limit?: number;
3254
+ }): Promise<UserCommentsResponse>;
3255
+ /**
3256
+ * Get subreddits moderated by a Reddit user.
3257
+ *
3258
+ * @param username - The Reddit username (without u/ prefix).
3259
+ * @returns Subreddits moderated by the user.
3260
+ * @throws NotFoundError - If the user doesn't exist.
3261
+ * @throws AuthenticationError - If the API key is invalid.
3262
+ *
3263
+ * @example
3264
+ * ```typescript
3265
+ * const response = await client.reddit.users.moderated("spez");
3266
+ * for (const sub of response.subreddits) {
3267
+ * console.log(`r/${sub.display_name}: ${sub.subscribers.toLocaleString()} subscribers`);
3268
+ * }
3269
+ * ```
3270
+ */
3271
+ moderated(username: string): Promise<UserModeratedResponse>;
3272
+ /**
3273
+ * Get trophies awarded to a Reddit user.
3274
+ *
3275
+ * @param username - The Reddit username (without u/ prefix).
3276
+ * @returns List of trophies awarded to the user.
3277
+ * @throws NotFoundError - If the user doesn't exist.
3278
+ * @throws AuthenticationError - If the API key is invalid.
3279
+ *
3280
+ * @example
3281
+ * ```typescript
3282
+ * const response = await client.reddit.users.trophies("spez");
3283
+ * for (const trophy of response.trophies) {
3284
+ * console.log(`${trophy.name}${trophy.description ? `: ${trophy.description}` : ""}`);
3285
+ * }
3286
+ * ```
3287
+ */
3288
+ trophies(username: string): Promise<UserTrophiesResponse>;
3289
+ }
3290
+
3291
+ /**
3292
+ * Reddit API client.
3293
+ *
3294
+ * Provides access to all Reddit API endpoints through specialized sub-clients.
3295
+ */
3296
+
3297
+ /**
3298
+ * Reddit API client with access to all Reddit endpoints.
3299
+ *
3300
+ * Provides sub-clients for different resource types:
3301
+ * - `search` - Search posts, subreddits, users, and domain posts
3302
+ * - `posts` - Trending posts, post details, comments, and cross-posts
3303
+ * - `subreddits` - Subreddit details, posts, rules, moderators, and wiki pages
3304
+ * - `users` - User profiles, posts, comments, moderated subreddits, and trophies
3305
+ *
3306
+ * @example
3307
+ * ```typescript
3308
+ * const client = new ScrapeBadger({ apiKey: "key" });
3309
+ *
3310
+ * // Search posts
3311
+ * const results = await client.reddit.search.posts({ query: "typescript tips" });
3312
+ *
3313
+ * // Get subreddit details
3314
+ * const sub = await client.reddit.subreddits.get("programming");
3315
+ *
3316
+ * // Get user profile
3317
+ * const user = await client.reddit.users.get("spez");
3318
+ *
3319
+ * // Get trending posts
3320
+ * const trending = await client.reddit.posts.trending({ sort: "hot" });
3321
+ * ```
3322
+ */
3323
+ declare class RedditClient {
3324
+ /** Client for search operations (posts, subreddits, users, domain posts) */
3325
+ readonly search: SearchClient;
3326
+ /** Client for post operations (trending, details, comments, duplicates) */
3327
+ readonly posts: PostsClient;
3328
+ /** Client for subreddit operations (details, posts, rules, moderators, wiki) */
3329
+ readonly subreddits: SubredditsClient;
3330
+ /** Client for user operations (profile, posts, comments, moderated, trophies) */
3331
+ readonly users: UsersClient;
3332
+ /**
3333
+ * Create a new Reddit client.
3334
+ *
3335
+ * @param client - The base HTTP client for making requests.
3336
+ */
3337
+ constructor(client: BaseClient);
159
3338
  }
160
3339
 
161
3340
  /**
@@ -202,6 +3381,12 @@ declare class ScrapeBadger {
202
3381
  readonly twitter: TwitterClient;
203
3382
  /** Web scraping API client */
204
3383
  readonly web: WebClient;
3384
+ /** Vinted scraper API client */
3385
+ readonly vinted: VintedClient;
3386
+ /** Google Scraper API client — 19 Google product APIs */
3387
+ readonly google: GoogleClient;
3388
+ /** Reddit scraper API client */
3389
+ readonly reddit: RedditClient;
205
3390
  /**
206
3391
  * Create a new ScrapeBadger client.
207
3392
  *
@@ -230,4 +3415,4 @@ declare class ScrapeBadger {
230
3415
  constructor(config?: Partial<ScrapeBadgerConfig>);
231
3416
  }
232
3417
 
233
- export { type BatchOptions, type BatchResult, type ExtractOptions, type ExtractResult, ScrapeBadger, ScrapeBadgerConfig, type ScrapeOptions, type ScrapeResult, type ScreenshotOptions, type ScreenshotResult, type SessionInfo, TwitterClient, WebClient };
3418
+ export { type AiModeSearchParams, type AutocompleteParams, type DetectOptions, type DetectResult, type DomainPostsResponse, type FinanceQuoteParams, type FlightsSearchParams, type FlightsStopsFilter, type FlightsTravelClass, type FlightsTripType, AiModeClient as GoogleAiModeClient, AutocompleteClient as GoogleAutocompleteClient, GoogleClient, FinanceClient as GoogleFinanceClient, FlightsClient as GoogleFlightsClient, HotelsClient as GoogleHotelsClient, ImagesClient as GoogleImagesClient, JobsClient as GoogleJobsClient, LensClient as GoogleLensClient, MapsClient as GoogleMapsClient, NewsClient as GoogleNewsClient, PatentsClient as GooglePatentsClient, ProductsClient as GoogleProductsClient, type GoogleResponse, ScholarClient as GoogleScholarClient, SearchClient$1 as GoogleSearchClient, type GoogleSearchParams, ShoppingClient as GoogleShoppingClient, ShortsClient as GoogleShortsClient, TrendsClient as GoogleTrendsClient, VideosClient as GoogleVideosClient, type HotelsDetailsParams, type HotelsSearchParams, type ImagesSearchParams, type JobsSearchParams, type LensSearchParams, type MapsPhotosParams, type MapsPlaceParams, type MapsPostsParams, type MapsReviewsParams, type MapsSearchParams, type NewsSearchParams, type NewsTopicsParams, type NewsTrendingParams, type PatentsDetailParams, type PatentsSearchParams, type PopularSubredditsResponse, type PostCommentsResponse, type PostDetailResponse, type PostDuplicatesResponse, type ProductsDetailParams, RedditClient, type RedditComment, type RedditModerator, type RedditPagination, type RedditPost, PostsClient as RedditPostsClient, type RedditRule, SearchClient as RedditSearchClient, type RedditSubreddit, SubredditsClient as RedditSubredditsClient, type RedditTrophy, type RedditUser, type UserProfileResponse as RedditUserProfileResponse, UsersClient as RedditUsersClient, type RedditWikiPage, type ScholarAuthorCitationParams, type ScholarAuthorParams, type ScholarCiteParams, type ScholarProfilesParams, type ScholarSearchParams, ScrapeBadger, ScrapeBadgerConfig, type ScrapeOptions, type ScrapeResult, type SearchPostsResponse, type SearchSubredditsResponse, type SearchUsersResponse, type ShoppingClickParams, type ShoppingProductParams, type ShoppingSearchParams, type ShortsSearchParams, type SubredditDetailResponse, type SubredditModeratorsResponse, type SubredditPostsResponse, type SubredditRulesResponse, type SubredditWikiPagesResponse, type TrendingPostsResponse, type TrendsAutocompleteParams, type TrendsInterestParams, type TrendsRegionsParams, type TrendsRelatedParams, type TrendsTrendingParams, TwitterClient, type UserCommentsResponse, type UserModeratedResponse, type UserPostsResponse, type UserTrophiesResponse, type VideosSearchParams, type VintedBrand, type BrandsResponse as VintedBrandsResponse, VintedClient, type VintedColor, type ColorsResponse as VintedColorsResponse, type VintedItemDetail, type ItemDetailResponse as VintedItemDetailResponse, type VintedItemSummary, ItemsClient as VintedItemsClient, type VintedMarket, type MarketsResponse as VintedMarketsResponse, type VintedPagination, type VintedPhoto, type VintedPrice, ReferenceClient as VintedReferenceClient, SearchClient$2 as VintedSearchClient, type VintedSearchParams, type SearchResponse as VintedSearchResponse, type VintedSellerSummary, type VintedStatus, type StatusesResponse as VintedStatusesResponse, type UserItemsResponse as VintedUserItemsResponse, type VintedUserProfile, type UserProfileResponse$1 as VintedUserProfileResponse, type VintedUserSummary, UsersClient$1 as VintedUsersClient, WebClient, type WikiPageResponse };