@scrapecreators/cli 1.0.27 → 1.0.29

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.
@@ -3,11 +3,23 @@ import { tiktokShopApis } from "./tiktok-shop-apis.js";
3
3
  import { instagramBaseApis } from "./instagram-apis.js";
4
4
  import { githubApis } from "./github-apis.js";
5
5
  import { kwaiApis } from "./kwai-apis.js";
6
+ import { telegramApis } from "./telegram-apis.js";
7
+
8
+ const withPostVariant = (endpoint) => [
9
+ endpoint,
10
+ {
11
+ ...endpoint,
12
+ method: "POST",
13
+ docsPath: `${endpoint.path}/post`,
14
+ postParamsInBody: true,
15
+ },
16
+ ];
6
17
 
7
18
  export const apis = [
8
19
  tiktokBaseApis,
9
20
  tiktokShopApis,
10
21
  instagramBaseApis,
22
+ telegramApis,
11
23
  {
12
24
  id: "youtube",
13
25
  name: "YouTube",
@@ -19,7 +31,7 @@ export const apis = [
19
31
  description:
20
32
  "Get comprehensive channel information including stats and metadata. Can pass channelId, handle, or url.",
21
33
  fullDescription:
22
- "Retrieves comprehensive YouTube channel profile data including name, avatar images, subscriber count (subscribers), total video and view counts, join date, tags, and linked social accounts like Twitter and Instagram. Accepts a channelId, handle, or full channel URL as input. Returns channel metadata such as country, email, and external store links when available.",
34
+ "Retrieves comprehensive YouTube channel profile data including name, avatar images, subscriber count (subscribers), total video and view counts, join date, tags, and linked social accounts like Twitter and Instagram. Accepts a channelId, handle, or full channel URL as input. Returns channel metadata such as country, email, and external store links when available. Contact fields come from the submitted public profile. To request removal of your own information from Scrape Creators results, email support@scrapecreators.com with the profile URL.",
23
35
  path: "/v1/youtube/channel",
24
36
  sampleResponse: {
25
37
  channelId: "UCxcTeAKWJca6XyJ37_ZoKIQ",
@@ -576,10 +588,41 @@ export const apis = [
576
588
  name: "Video/Short Details",
577
589
  method: "GET",
578
590
  description:
579
- "Get complete information about a video or short.",
591
+ "Get complete information about a video or short. isPaidPromotion tells you whether YouTube marks the video as including paid promotion. Also includes YouTube's most-replayed heatmap when YouTube exposes it. most_replayed is null when the graph is not available. Age-restricted videos return 403 because we only use the public logged-out YouTube source.",
580
592
  fullDescription:
581
- "Fetches full details for a YouTube video or short, including title, description, thumbnail, view count (views), like count (likes), comment count, publish date, duration, genre, keywords, chapters, collaborators, and available caption tracks (subtitles/captions). Also returns related recommended videos in watchNextVideos and channel info for the uploader.",
593
+ "Fetches full details for a YouTube video or short, including title, description, thumbnail, view count (views), like count (likes), comment count, publish date, duration, genre, keywords, chapters, collaborators, and available caption tracks (subtitles/captions). isPaidPromotion is true when YouTube marks the video as including paid promotion and false when it does not. Also returns related recommended videos in watchNextVideos and channel info for the uploader. When YouTube exposes its public Most replayed graph, most_replayed contains normalized graph buckets in markers and YouTube's highlighted ranges in ranges. The field is null when the graph is not available. YouTube says the graph may be unavailable when the channel has active strikes, the content is potentially inappropriate, the video is too new or has too few views, or its systems deem the video ineligible for another reason. YouTube does not publish fixed age or view-count thresholds. Age-restricted videos return 403 with message: \"This video is age restricted\" because Scrape Creators only uses the public logged-out YouTube source.",
582
594
  path: "/v1/youtube/video",
595
+ errorResponseExamples: {
596
+ 403: {
597
+ success: false,
598
+ credits_remaining: 100,
599
+ error: "forbidden",
600
+ errorStatus: 403,
601
+ message: "This video is age restricted",
602
+ },
603
+ },
604
+ responseFields: [
605
+ {
606
+ path: "isPaidPromotion",
607
+ description:
608
+ "Boolean. True when YouTube marks the video as including paid promotion; otherwise false.",
609
+ },
610
+ {
611
+ path: "most_replayed",
612
+ description:
613
+ "YouTube's public Most replayed heatmap, or null when YouTube does not show the graph for this video.",
614
+ },
615
+ {
616
+ path: "most_replayed.markers",
617
+ description:
618
+ "Graph buckets with startMillis, durationMillis, and intensityScoreNormalized.",
619
+ },
620
+ {
621
+ path: "most_replayed.ranges",
622
+ description:
623
+ "YouTube-highlighted replay ranges with visibleTimeRangeStartMillis, visibleTimeRangeEndMillis, decorationTimeMillis, and the localized label.",
624
+ },
625
+ ],
583
626
  sampleResponse: {
584
627
  success: true,
585
628
  credits_remaining: 33851527,
@@ -655,6 +698,8 @@ export const apis = [
655
698
  genre: "People & Blogs",
656
699
  durationMs: 348000,
657
700
  durationFormatted: "00:05:48",
701
+ isPaidPromotion: false,
702
+ most_replayed: null,
658
703
  captionTracks: [
659
704
  {
660
705
  baseUrl:
@@ -679,7 +724,7 @@ export const apis = [
679
724
  type: "string",
680
725
  required: true,
681
726
  description: "YouTube video or short URL",
682
- placeholder: "https://www.youtube.com/watch?v=Y2Ah_DFr8cw",
727
+ placeholder: "https://youtu.be/gTCi7PaOPLY",
683
728
  },
684
729
  {
685
730
  name: "language",
@@ -693,9 +738,9 @@ export const apis = [
693
738
  {
694
739
  name: "Transcript",
695
740
  method: "GET",
696
- description: "Get transcript of a video or short",
741
+ description: "Get publicly available captions or a transcript from a YouTube video or Short",
697
742
  fullDescription:
698
- "Retrieves the captions, subtitles, or transcript of a YouTube video or short. Returns both a timestamped transcript array with start/end times and a plain-text version in transcript_only_text. Supports specifying a language code. Note: the video must be under 2 minutes for transcript extraction to work.",
743
+ "Retrieves the captions, subtitles, or transcript of a YouTube video or Short. Returns both a timestamped transcript array with start/end times and a plain-text version in transcript_only_text. Supports specifying a language code. There is no two-minute limit for YouTube. Long videos, including podcasts, work when YouTube exposes public captions. If no matching caption track is available, the transcript fields return null.",
699
744
  path: "/v1/youtube/video/transcript",
700
745
  params: [
701
746
  {
@@ -1103,7 +1148,8 @@ export const apis = [
1103
1148
  name: "query",
1104
1149
  type: "string",
1105
1150
  required: true,
1106
- description: "Search query",
1151
+ description:
1152
+ 'Search query. For stricter title matching, use YouTube\'s intitle: operator, for example intitle:"Foursquare Swarm". Quoted queries by themselves may still be broadened by YouTube when no fresh exact matches are available.',
1107
1153
  },
1108
1154
  {
1109
1155
  name: "uploadDate",
@@ -1166,6 +1212,52 @@ export const apis = [
1166
1212
  },
1167
1213
  ],
1168
1214
  },
1215
+ {
1216
+ name: "Search Typeahead",
1217
+ method: "GET",
1218
+ description:
1219
+ "Get the live autocomplete suggestions shown in YouTube's search dropdown.",
1220
+ fullDescription:
1221
+ "Returns the live search suggestions YouTube displays while a user types. Each result includes the suggested text and whether it is a normal query or a channel. When YouTube returns a channel suggestion, the response also includes its public channel ID, handle, name, and thumbnail.",
1222
+ path: "/v1/youtube/search/typeahead",
1223
+ sampleResponse: {
1224
+ success: true,
1225
+ credits_remaining: 100,
1226
+ data: {
1227
+ query: "mr beast",
1228
+ suggestions: [
1229
+ {
1230
+ text: "mrbeast",
1231
+ type: "channel",
1232
+ channel: {
1233
+ id: "UCX6OQ3DkcsbYNE6H8uQQuVA",
1234
+ handle: "@MrBeast",
1235
+ name: "MrBeast",
1236
+ thumbnailUrl:
1237
+ "https://yt3.googleusercontent.com/example=s88-c-k-c0x00ffffff-no-rj",
1238
+ },
1239
+ },
1240
+ {
1241
+ text: "mr beast give me some money",
1242
+ type: "query",
1243
+ },
1244
+ {
1245
+ text: "mrbeast gaming",
1246
+ type: "query",
1247
+ },
1248
+ ],
1249
+ },
1250
+ },
1251
+ params: [
1252
+ {
1253
+ name: "query",
1254
+ type: "string",
1255
+ required: true,
1256
+ description: "Partial or complete YouTube search query",
1257
+ placeholder: "mr beast",
1258
+ },
1259
+ ],
1260
+ },
1169
1261
  {
1170
1262
  name: "Search by Hashtag",
1171
1263
  method: "GET",
@@ -2643,7 +2735,7 @@ export const apis = [
2643
2735
  description:
2644
2736
  "Search for public LinkedIn posts by keyword. Uses Google Search to find indexed posts, then scrapes the public LinkedIn pages.",
2645
2737
  fullDescription:
2646
- "Finds public LinkedIn posts, feed updates, and Pulse articles by keyword using Google Search, then returns post details such as description, author, media, images, like count, comment count, and published date when LinkedIn exposes them publicly. Results depend on what Google has indexed, so this is best-effort and not a complete LinkedIn-native search. Use date_posted for recent posts and pass the returned cursor to fetch the next page.",
2738
+ "Finds public LinkedIn posts, feed updates, and Pulse articles by keyword using Google Search, then returns post details such as description, author, media, images, like count, comment count, and published date when LinkedIn exposes them publicly. Results depend on what Google has indexed, so this is best-effort and not a complete LinkedIn-native search. Use date_posted for recent posts and pass the returned cursor to fetch the next page. Cursors are limited to pages 1 through 11; cursor 12 or greater returns a 400 response.",
2647
2739
  path: "/v1/linkedin/search/posts",
2648
2740
  paginationField: "cursor",
2649
2741
  params: [
@@ -2666,7 +2758,7 @@ export const apis = [
2666
2758
  name: "cursor",
2667
2759
  type: "string",
2668
2760
  required: false,
2669
- description: "The cursor returned from the previous response",
2761
+ description: "The cursor returned from the previous response. The maximum cursor is 11; cursor 12 or greater returns a 400 response.",
2670
2762
  placeholder: "2",
2671
2763
  },
2672
2764
  ],
@@ -2949,7 +3041,7 @@ export const apis = [
2949
3041
  method: "GET",
2950
3042
  description: "Get public Facebook profile information",
2951
3043
  fullDescription:
2952
- "Retrieves public Facebook page details including category, address, email, phone, website, services, priceRange, rating, likeCount, and followerCount. Also returns adLibrary status with the page's ad activity and pageId. Optionally includes businessHours when get_business_hours is set to true.",
3044
+ "Retrieves public Facebook page details including category, address, email, phone, website, services, priceRange, rating, likeCount, talkingAboutCount, and followerCount. talkingAboutCount is nullable and only returned when Facebook exposes it publicly. Also returns adLibrary status with the page's ad activity and pageId. Optionally includes businessHours when get_business_hours is set to true. Contact fields come from the submitted public profile. To request removal of your own information from Scrape Creators results, email support@scrapecreators.com with the profile URL. If Facebook shows an 18+ content gate, the response is still 200 with account_status: \"age-restricted\" and isPrivate: true. If Facebook shows a private content gate, the response is still 200 with account_status: \"private\" and isPrivate: true. If the page is not found, the response is 404 with accountDoesNotExist: true and isPrivate: false. Set include_gated_profile=true to also return limited public fields (such as id, name, category, likeCount, profilePicSmall, and links) when a profile is gated or age-restricted. This option only affects gated/age-restricted profiles — public profiles still return the normal full response.",
2953
3045
  path: "/v1/facebook/profile",
2954
3046
  sampleResponse: {
2955
3047
  success: true,
@@ -3072,6 +3164,7 @@ export const apis = [
3072
3164
  },
3073
3165
  ],
3074
3166
  id: "100088017857524",
3167
+ isPrivate: false,
3075
3168
  name: "Mantraindian",
3076
3169
  url: "https://www.facebook.com/mantraindianfolsom",
3077
3170
  gender: "UNKNOWN",
@@ -3127,8 +3220,56 @@ export const apis = [
3127
3220
  rating: "Not yet rated (1 review)",
3128
3221
  ratingCount: null,
3129
3222
  likeCount: 3224,
3223
+ talkingAboutCount: 418,
3130
3224
  followerCount: 3200,
3131
3225
  },
3226
+ privateResponse: {
3227
+ success: true,
3228
+ credits_remaining: 100,
3229
+ url: "https://www.facebook.com/VinnysDriveBar/",
3230
+ account_status: "private",
3231
+ isPrivate: true,
3232
+ message: "Profile is private",
3233
+ },
3234
+ ageRestrictedResponse: {
3235
+ success: true,
3236
+ credits_remaining: 100,
3237
+ url: "https://www.facebook.com/profile.php?id=999244349946937",
3238
+ account_status: "age-restricted",
3239
+ isPrivate: true,
3240
+ message: "Profile is age restricted",
3241
+ },
3242
+ gatedProfileResponse: {
3243
+ success: true,
3244
+ credits_remaining: 298984,
3245
+ id: "1581499185460975",
3246
+ name: "Galopim Livros",
3247
+ url: "https://www.facebook.com/livrosgalopim/",
3248
+ profilePicSmall:
3249
+ "https://scontent-phl2-1.xx.fbcdn.net/v/t39.30808-1/459791315_1253431156111407_5370275117423562096_n.jpg?stp=dst-jpg_p200x200_tt6&_nc_cat=110&ccb=1-7&_nc_sid=418b77&_nc_ohc=Pi3YpShkQiYQ7kNvwEYPNxb&_nc_oc=AdrjmBEW-EsVxhFGkvcfpAoKyqM65UHc9gnY6PsWlNZdu2_nIx1mc6tK9SAVVvNgUYg&_nc_zt=24&_nc_ht=scontent-phl2-1.xx&_nc_gid=aEVhmS9KLeHxBKf28_0baA&_nc_ss=7f289&oh=00_AQBmzIQzEFDGjobJ0GwIzhko6nFrshbjeDFEUKLwK_bQIg&oe=6A652D51",
3250
+ category: "Bookstore",
3251
+ links: ["https://www.instagram.com/livros_galopim/"],
3252
+ likeCount: 16576,
3253
+ pageAlias: "livrosgalopim",
3254
+ verification: "NOT_VERIFIED",
3255
+ entityType: "PERSON_PROFILE",
3256
+ igUsername: "livros_galopim",
3257
+ igFollowerCount: 657,
3258
+ igVerification: false,
3259
+ pageIsDeleted: false,
3260
+ },
3261
+ errorResponseExamples: {
3262
+ 404: {
3263
+ success: true,
3264
+ credits_remaining: 100,
3265
+ data: {
3266
+ url: "https://www.facebook.com/TatnuckDrivingRangeandIceCream/",
3267
+ accountDoesNotExist: true,
3268
+ isPrivate: false,
3269
+ message: "Account doesn't exist",
3270
+ },
3271
+ },
3272
+ },
3132
3273
  params: [
3133
3274
  {
3134
3275
  name: "url",
@@ -3144,6 +3285,14 @@ export const apis = [
3144
3285
  description: "Get the business's hours",
3145
3286
  placeholder: "true",
3146
3287
  },
3288
+ {
3289
+ name: "include_gated_profile",
3290
+ type: "string",
3291
+ required: false,
3292
+ description:
3293
+ "When true, returns limited public fields for gated or age-restricted profiles. Ignored for normal public profiles — those still return the full response.",
3294
+ placeholder: "true",
3295
+ },
3147
3296
  ],
3148
3297
  },
3149
3298
  {
@@ -4578,13 +4727,92 @@ export const apis = [
4578
4727
  "has_next_page": true
4579
4728
  },
4580
4729
  },
4730
+ {
4731
+ name: "Facebook Group Info",
4732
+ method: "GET",
4733
+ description: "Get the public About-page information for a Facebook group.",
4734
+ fullDescription:
4735
+ "Fetches the public information shown on a Facebook group's About page, including its description, privacy and visibility, member and activity counts, categories, administrators and moderators when Facebook exposes them, group history, and rules. Provide either url or group_id.",
4736
+ path: "/v1/facebook/group",
4737
+ params: [
4738
+ {
4739
+ name: "url",
4740
+ type: "string",
4741
+ description: "The Facebook group URL. Group sub-page URLs such as /about work too.",
4742
+ required: false,
4743
+ placeholder: "https://www.facebook.com/groups/366190054572553/about",
4744
+ },
4745
+ {
4746
+ name: "group_id",
4747
+ type: "string",
4748
+ description: "The numeric Facebook group ID. Provide this instead of url if you already have it.",
4749
+ required: false,
4750
+ placeholder: "366190054572553",
4751
+ },
4752
+ ],
4753
+ sampleResponse: {
4754
+ success: true,
4755
+ credits_remaining: 49999999999,
4756
+ credits_charged: 1,
4757
+ id: "366190054572553",
4758
+ url: "https://www.facebook.com/groups/366190054572553",
4759
+ name: "Python Programming",
4760
+ description: "Let's share our knowledge on Python Programming",
4761
+ privacy: {
4762
+ label: "Public",
4763
+ description: "Anyone can see who's in the group and what they post.",
4764
+ },
4765
+ visibility: {
4766
+ label: "Visible",
4767
+ description: "Anyone can find this group.",
4768
+ },
4769
+ categories: [
4770
+ { id: "242504017103922", name: "Software & tech" },
4771
+ { id: "202183377053878", name: "Engineering" },
4772
+ ],
4773
+ created_at: "2020-10-14T15:45:03.000Z",
4774
+ history_summary: "Group created on October 14, 2020. Name last changed on October 16, 2020.",
4775
+ member_count: 710386,
4776
+ member_count_text: "710,386 total members",
4777
+ administrator_count: 3,
4778
+ moderator_count: 0,
4779
+ administrators: [
4780
+ {
4781
+ id: "pfbid029b9bjf9rZfL4v9EHdxt1uxng857G4UqwpZjbCHySg88UYWu2XL5ivSixWhXBnZMnl",
4782
+ name: "Nusrat Jahan",
4783
+ url: "https://www.facebook.com/people/Nusrat-Jahan/pfbid029b9bjf9rZfL4v9EHdxt1uxng857G4UqwpZjbCHySg88UYWu2XL5ivSixWhXBnZMnl/",
4784
+ profile_picture_url: "https://scontent.xx.fbcdn.net/example.jpg",
4785
+ },
4786
+ ],
4787
+ moderators: [],
4788
+ activity: {
4789
+ posts_last_day: 16,
4790
+ posts_last_month: 512,
4791
+ new_members_text: "No new members in the last week",
4792
+ },
4793
+ rules: [
4794
+ {
4795
+ id: "366191957905696",
4796
+ title: "Be Kind and Courteous",
4797
+ description: "We're all in this together to create a welcoming environment. Let's treat everyone with respect.",
4798
+ },
4799
+ ],
4800
+ about_info: [
4801
+ {
4802
+ type: "XFBPrivacyGroupsAboutInfoItem",
4803
+ label: "Public",
4804
+ description: "Anyone can see who's in the group and what they post.",
4805
+ },
4806
+ ],
4807
+ },
4808
+ },
4581
4809
  {
4582
4810
  name: "Facebook Group Posts",
4583
4811
  method: "GET",
4584
4812
  description:
4585
4813
  "Get a public Facebook groups posts. Only can get 3 posts at a time :( (Facebook API limit)",
4586
4814
  fullDescription:
4587
- "Fetches posts from a public Facebook group, limited to 3 posts per page due to API limitations. Each post includes id, text, url, reactionCount, commentCount, publishTime, videoDetails, and topComments. Supports sorting by TOP_POSTS, RECENT_ACTIVITY, CHRONOLOGICAL, or CHRONOLOGICAL_LISTINGS, with cursor-based pagination.",
4815
+ "Fetches posts from a public Facebook group, limited to 3 posts per page due to API limitations. Each post includes id, text, url, reactionCount, commentCount, publishTime, videoDetails, and topComments. Results are chronological by default. Supports TOP_POSTS, RECENT_ACTIVITY, CHRONOLOGICAL, and CHRONOLOGICAL_LISTINGS with cursor-based pagination.",
4588
4816
  path: "/v1/facebook/group/posts",
4589
4817
  params: [
4590
4818
  {
@@ -4604,9 +4832,9 @@ export const apis = [
4604
4832
  {
4605
4833
  name: "sort_by",
4606
4834
  type: "select",
4607
- description: "How to sort the posts",
4835
+ description: "How to sort the posts. Defaults to CHRONOLOGICAL.",
4608
4836
  required: false,
4609
- placeholder: "TOP_POSTS",
4837
+ placeholder: "CHRONOLOGICAL",
4610
4838
  options: [
4611
4839
  "TOP_POSTS",
4612
4840
  "RECENT_ACTIVITY",
@@ -4842,7 +5070,7 @@ export const apis = [
4842
5070
  method: "GET",
4843
5071
  description: "Search Facebook Marketplace listings",
4844
5072
  fullDescription:
4845
- "Searches Facebook Marketplace listings by keyword and lat/lng. Supports pagination with the returned cursor. Pass the cursor value back as-is. When sort_by is creation_time_descend, Facebook can still return slightly different ordering between identical requests. For alerting/new-item workflows, scrape multiple pages and dedupe by listing id instead of relying on page 1 item order being identical every run.",
5073
+ "Searches Facebook Marketplace listings by keyword and lat/lng. Pass category_id to restrict results to the numeric Facebook Marketplace category ID returned on listing results. Supports pagination with the returned cursor. Pass the cursor value back as-is. When sort_by is creation_time_descend, Facebook can still return slightly different ordering between identical requests. For alerting/new-item workflows, scrape multiple pages and dedupe by listing id instead of relying on page 1 item order being identical every run.",
4846
5074
  path: "/v1/facebook/marketplace/search",
4847
5075
  params: [
4848
5076
  {
@@ -4852,6 +5080,13 @@ export const apis = [
4852
5080
  required: true,
4853
5081
  placeholder: "bike",
4854
5082
  },
5083
+ {
5084
+ name: "category_id",
5085
+ type: "string",
5086
+ description: "Numeric Facebook Marketplace category ID. Listing results include this value as category_id.",
5087
+ required: false,
5088
+ placeholder: "1658310421102081",
5089
+ },
4855
5090
  {
4856
5091
  name: "lat",
4857
5092
  type: "number",
@@ -5081,9 +5316,9 @@ export const apis = [
5081
5316
  {
5082
5317
  name: "Marketplace Item",
5083
5318
  method: "GET",
5084
- description: "Get a Facebook Marketplace item",
5319
+ description: "Get a Facebook Marketplace item, including rental listing_date_text and availability_text when Facebook exposes them.",
5085
5320
  fullDescription:
5086
- "Fetches details for a Facebook Marketplace item by item id or Marketplace item URL, including title, description, price, location, condition, photos, seller, and availability flags.",
5321
+ "Fetches details for a Facebook Marketplace item by item id or Marketplace item URL, including title, description, price, location, condition, photos, seller, and availability flags. Rental listings can include listing_date_text and availability_text from Facebook's Marketplace GraphQL response, for example 'Listed over a week ago' and 'Available now'. creation_time can still be null when Facebook does not expose an exact timestamp.",
5087
5322
  path: "/v1/facebook/marketplace/item",
5088
5323
  params: [
5089
5324
  {
@@ -5109,6 +5344,8 @@ export const apis = [
5109
5344
  "title": "Specialized Hardrock GSX - Super Clean Vintage Restomod - INCLUDES FREE TUNE UP",
5110
5345
  "description": "Was going to hang on to this one bc I absolutely love how it looks, but the 20” frame is just bit too large for me. Riders over 6’ would be comfy on this one. Currently in a 3x7 set up with an XT derailleur at the rear. Looks great in person. Come ride it! These never last long. \n\nCASH ONLY, PLEASE. NEAR 183/BRAKER. \n\n$380 OBO. \n\nKey points:\n\n- Maxxis DTH tires (26”)\n- Shimano Deore XT rear derailleur \n- Shimano front derailleur\n- vintage Specialized steel frame (20”)\n- vintage Sakae triple crankset (170mm)\n- vintage Sakae SR Custom handlebar\n- vintage Suntour stem shifter\n- vintage Shimano brakes\n- Specialized Avatar 143 saddle\n- new chain\n- fresh cables\n- fresh housing\n- fresh grease and lube\n- fresh lube in cable housings\n- fresh handlebar tape\n- drive train cleaned and lubed\n- derailluers adjusted and fine tuned\n- brakes adjusted and fine tuned\n- deep cleaning/detail\n- frame polished\n- frame waxed\n- INCLUDES ONE FREE TUNE UP\n",
5111
5346
  "creation_time": "2026-05-15T16:57:39.000Z",
5347
+ "listing_date_text": null,
5348
+ "availability_text": null,
5112
5349
  "location_text": "Austin, TX",
5113
5350
  "location": {
5114
5351
  "latitude": 30.401916503906,
@@ -5719,7 +5956,7 @@ export const apis = [
5719
5956
  description:
5720
5957
  "Pass the Ad ID and get back details about the ad. Be careful that if an ad has multiple versions, you're actually going to want to get the title from the 'cards' object.",
5721
5958
  fullDescription:
5722
- "Retrieves detailed information about a specific Facebook ad by its ID or URL. Returns adArchiveID, pageName, isActive, startDate, endDate, and a snapshot containing body, images, videos, display_format, link_url, and cta_text. For ads with multiple versions, the ad creative is found in the snapshot.cards array rather than snapshot.body.",
5959
+ "Retrieves detailed information about a specific Facebook ad by its ID or URL. Returns adArchiveID, pageName, isActive, startDate, endDate, and a snapshot containing body, images, videos, display_format, link_url, and cta_text. Regulated ads may also include source-dependent aaa_info using the structure shown below. Political and social issue delivery data is normalized to location_audience and age_country_gender_reach_breakdown. Political location_audience rows include reach, and political delivery values are fractional shares, so 0.08 means 8%. Regional transparency data may use absolute reach counts. For ads with multiple versions, the ad creative is found in the snapshot.cards array rather than snapshot.body.",
5723
5960
  path: "/v1/facebook/adLibrary/ad",
5724
5961
  sampleResponse: {
5725
5962
  adid: 0,
@@ -6104,13 +6341,13 @@ export const apis = [
6104
6341
  },
6105
6342
  ],
6106
6343
  },
6107
- {
6344
+ ...withPostVariant({
6108
6345
  name: "Search",
6109
6346
  method: "GET",
6110
6347
  description:
6111
- "Search the Facebook (Meta) Ad Library By Keyword. This endpoint will tap out around 1,500 results, beacuse the cursor becomes too big for a GET request. If you need more results, call this endpoint as a POST, and pass the query params in the body.",
6348
+ "Search the Facebook (Meta) Ad Library by keyword. Use GET for normal requests. If the cursor becomes too large after extensive pagination, use POST and send the same parameters in the JSON body.",
6112
6349
  fullDescription:
6113
- "Searches the Meta Ad Library by keyword and returns matching ads. Each result includes ad_archive_id, page_name, is_active, publisher_platform, and a snapshot with body text, images, videos, and cta_text. Results cap around 1,500 via GET due to cursor size limits; switch to POST method with body params for larger result sets.",
6350
+ "Searches the Meta Ad Library by keyword and returns matching ads. Supports filtering by language with a 2-letter code such as EN or ES. Each result includes ad_archive_id, page_name, is_active, publisher_platform, and a snapshot with body text, images, videos, and cta_text. Both GET and POST are supported. Use GET for normal requests. If the cursor becomes too large after extensive pagination, use POST and send the same parameters in the JSON body.",
6114
6351
  path: "/v1/facebook/adLibrary/search/ads",
6115
6352
  sampleResponse: {
6116
6353
  searchResults: [
@@ -6366,6 +6603,14 @@ export const apis = [
6366
6603
  "This can only be one country. It has to be the 2 letter code for the country. It defaults to ALL.",
6367
6604
  placeholder: "ALL",
6368
6605
  },
6606
+ {
6607
+ name: "language",
6608
+ type: "string",
6609
+ required: false,
6610
+ description:
6611
+ "Language to filter ads on. Needs to be a 2 letter language code, such as EN, ES, or FR.",
6612
+ placeholder: "EN",
6613
+ },
6369
6614
  {
6370
6615
  name: "status",
6371
6616
  type: "select",
@@ -6423,15 +6668,15 @@ export const apis = [
6423
6668
  placeholder: "false",
6424
6669
  },
6425
6670
  ],
6426
- },
6427
- {
6671
+ }),
6672
+ ...withPostVariant({
6428
6673
  name: "Company Ads",
6429
6674
  method: "GET",
6430
6675
  paginationField: "cursor",
6431
6676
  description:
6432
- "Get all the ads a company has running. If params become too large, make this a POST request and pass the params in the body.",
6677
+ "Get all the ads a company has running. Use GET for normal requests. If the cursor becomes too large after extensive pagination, use POST and send the same parameters in the JSON body.",
6433
6678
  fullDescription:
6434
- "Fetches all ads currently running for a specific company from the Meta Ad Library. Each ad includes ad_archive_id, page_name, is_active, publisher_platform, and a snapshot with body, images, videos, and display_format. Supports filtering by country, media_type, date range, and language with cursor-based pagination.",
6679
+ "Fetches all ads currently running for a specific company from the Meta Ad Library. Each ad includes ad_archive_id, page_name, is_active, publisher_platform, and a snapshot with body, images, videos, and display_format. Supports filtering by country, media_type, date range, and language with cursor-based pagination. Both GET and POST are supported. If the cursor becomes too large after extensive pagination, use POST and send the same parameters in the JSON body.",
6435
6680
  path: "/v1/facebook/adLibrary/company/ads",
6436
6681
  youtubeId: "M_wgqCtznjM",
6437
6682
  codeExample:
@@ -6757,7 +7002,7 @@ export const apis = [
6757
7002
  placeholder: "false",
6758
7003
  },
6759
7004
  ],
6760
- },
7005
+ }),
6761
7006
  {
6762
7007
  name: "Search for Companies",
6763
7008
  method: "GET",
@@ -6825,187 +7070,95 @@ export const apis = [
6825
7070
  {
6826
7071
  name: "Ad Library Search",
6827
7072
  method: "GET",
6828
- description: "Search TikTok Creative Center Top Ads by region, period, and keyword.",
7073
+ description: "Search TikTok's public Ads Library by general query or advertiser name.",
6829
7074
  fullDescription:
6830
- "Searches TikTok Creative Center Top Ads, the ad library page at ads.tiktok.com/business/creativecenter/inspiration/topads. Supports US and other 2-letter regions, period filters, sorting, keyword search, and cursor pagination. Returns TikTok's public top ad material objects, including ad title, metrics, video info, landing page, and pagination.",
7075
+ "Searches TikTok's public Ads Library using either query for a general search or advertiser_name for advertiser-specific results. Advertiser-name searches resolve the name through TikTok's advertiser typeahead first, then search the selected advertiser entity. If TikTok has no matching entity, the API falls back to TikTok's name search so inputs such as The Creator Loop still return matching ads. Provide exactly one of query or advertiser_name. Results are global, sorted by the latest shown date, support cursor pagination, and include a public TikTok Ads Library URL for each ad.",
6831
7076
  path: "/v1/tiktok/ad-library/search",
6832
7077
  params: [
6833
- {
6834
- name: "region",
6835
- type: "select",
6836
- required: false,
6837
- description: "Country code. Defaults to US.",
6838
- options: ["DZ", "AR", "AU", "AT", "AZ", "BH", "BD", "BY", "BE", "BO", "BR", "BG", "KH", "CA", "CL", "CO", "CR", "HR", "CY", "CZ", "DK", "DO", "EC", "EG", "EE", "FI", "FR", "DE", "GR", "GT", "JO", "HU", "ID", "IQ", "IE", "IL", "IT", "JP", "KZ", "KE", "KW", "LV", "LB", "MY", "MX", "MA", "NL", "NZ", "NG", "NO", "OM", "PK", "PA", "PY", "PE", "PH", "PL", "PT", "PR", "QA", "LT", "RO", "SA", "RS", "SG", "SK", "SI", "ZA", "KR", "ES", "LK", "SE", "CH", "TW", "TH", "TR", "AE", "GB", "US", "UY", "VN"],
6839
- placeholder: "US",
6840
- },
6841
- {
6842
- name: "period",
6843
- type: "select",
6844
- required: false,
6845
- description: "Time window for Top Ads.",
6846
- options: ["7", "30", "180"],
6847
- placeholder: "30",
6848
- },
6849
7078
  {
6850
7079
  name: "query",
6851
7080
  type: "string",
6852
7081
  required: false,
6853
- description: "Optional keyword to search ad titles/content.",
6854
- placeholder: "spotify",
7082
+ description: "General ad search. Provide either query or advertiser_name, not both.",
7083
+ placeholder: "The Creator Loop",
6855
7084
  },
6856
7085
  {
6857
- name: "order_by",
6858
- type: "select",
6859
- required: false,
6860
- description: "Sort metric. Defaults to for_you.",
6861
- options: ["for_you", "impression", "play_2s_rate", "play_6s_rate", "cvr", "ctr", "like"],
6862
- placeholder: "for_you",
6863
- },
6864
- {
6865
- name: "industry",
6866
- type: "select",
6867
- required: false,
6868
- description: "Industry filter.",
6869
- options: ["apparel_accessories", "appliances", "apps", "baby_kids_maternity", "beauty_personal_care", "business_services", "ecommerce_non_app", "education", "financial_services", "food_beverage", "games", "health", "home_improvement", "household_products", "life_services", "news_entertainment", "pets", "sports_outdoor", "tech_electronics", "travel", "vehicle_transportation"],
6870
- placeholder: "beauty_personal_care",
6871
- },
6872
- {
6873
- name: "objective",
6874
- type: "select",
6875
- required: false,
6876
- description: "Campaign objective filter.",
6877
- options: ["app_installs", "conversions", "lead_generation", "product_sales", "reach", "traffic", "video_views"],
6878
- placeholder: "traffic",
6879
- },
6880
- {
6881
- name: "duration",
6882
- type: "select",
6883
- required: false,
6884
- description: "Video duration filter.",
6885
- options: ["under_10s", "10_20s", "20_30s", "30_40s", "40_50s", "over_50s"],
6886
- placeholder: "under_10s",
6887
- },
6888
- {
6889
- name: "likes",
6890
- type: "select",
6891
- required: false,
6892
- description: "Likes percentile filter.",
6893
- options: ["top_1_20", "top_21_40", "top_41_60", "top_61_80", "top_81_100"],
6894
- placeholder: "top_1_20",
6895
- },
6896
- {
6897
- name: "ad_format",
6898
- type: "select",
6899
- required: false,
6900
- description: "Ad format filter.",
6901
- options: ["spark_ads", "non_spark_ads"],
6902
- placeholder: "spark_ads",
6903
- },
6904
- {
6905
- name: "ad_language",
6906
- type: "select",
7086
+ name: "advertiser_name",
7087
+ type: "string",
6907
7088
  required: false,
6908
- description: "Ad language filter.",
6909
- options: ["en", "es", "ar", "vi", "th", "de", "id", "pt", "fr", "ms", "nl", "ja", "it", "ro", "zh-Hant", "ko"],
6910
- placeholder: "en",
7089
+ description: "Advertiser name to resolve through TikTok's typeahead and search by advertiser entity. Falls back to TikTok's name search when no entity matches. Provide either advertiser_name or query, not both.",
7090
+ placeholder: "Gymshark",
6911
7091
  },
6912
7092
  {
6913
7093
  name: "cursor",
6914
- type: "number",
6915
- required: false,
6916
- description: "Page number to fetch. Use the cursor returned from the previous response, like 3 for page 3.",
6917
- placeholder: "3",
6918
- },
6919
- {
6920
- name: "limit",
6921
- type: "number",
7094
+ type: "string",
6922
7095
  required: false,
6923
- description: "Number of ads to return, max 50. Defaults to 20.",
6924
- placeholder: "20",
7096
+ description: "Opaque cursor returned from the previous response.",
7097
+ placeholder: "cursor from previous response",
6925
7098
  },
6926
7099
  ],
6927
7100
  sampleResponse: {
6928
- "success": true,
6929
- "credits_remaining": 49996315011,
6930
- "query": "",
6931
- "region": "US",
6932
- "period": 30,
6933
- "ads": [
7101
+ success: true,
7102
+ credits_remaining: 100,
7103
+ credits_charged: 1,
7104
+ source: "tiktok_public_ads_library",
7105
+ advertiser_name: "Gymshark",
7106
+ resolved_advertiser_name: "GYMSHARK LTD",
7107
+ advertiser_matches: [
6934
7108
  {
6935
- "ad_title": "I thought this was a gimmick until I tried it! A wrinkled shirt, one button, and a few minutes later... ready to wear. Tap the link in bio and see why everyone’s talking about Bellairon before it sells out. @Bellairon LLC ",
6936
- "brand_name": "",
6937
- "cost": 1,
6938
- "ctr": 0.5,
6939
- "favorite": false,
6940
- "id": "7646829987799334920",
6941
- "industry_key": "label_22108000000",
6942
- "is_search": true,
6943
- "like": 92,
6944
- "objective_key": "campaign_objective_reach",
6945
- "video_info": {
6946
- "vid": "v12044gd0000d8erq07og65h1cq991gg",
6947
- "duration": 89.767,
6948
- "cover": "https://p16-common-sign.tiktokcdn.com/tos-maliva-p-0068c799-us/oIbqBdvfEAiFpgvAOgrQHCF5R0mkDDLiEfvQDS~tplv-noop.image?dr=18692&refresh_token=2ac068a9&x-expires=1781231816&x-signature=hLbBkguntM4oX9tgdnKMMDYixAA%3D&t=9276707c&ps=14f1eb3e&shp=9e36835a&shcp=317596d8&idc=my2&VideoID=v12044gd0000d8erq07og65h1cq991gg",
6949
- "video_url": {
6950
- "540p": "https://v16m-default.tiktokcdn.com/64e64ad32f68588eee511da0114f0f2e/6a2b70c8/video/tos/maliva/tos-maliva-ve-0068c799-us/oIN2GPIRgHAUBHOeNfLk2HBSERoJeIALGC3jAE/?a=0&bti=NTU4QDM1NGA%3D&&bt=315&ft=cApXJCz7ThWHK-z9LGZmo0P&mime_type=video_mp4&rc=Omk6ZWQ7Nzc7OGY8PGVnOkBpajQ8Zms5cjN1OzMzZzczNEBgNDAzXl9hXjMxLzEvXjFiYSNkNm4uMmQ0bmJhLS1kMS9zcw%3D%3D&vvpl=1&l=20260612043527C18C959B9A8CF584D398&btag=e00090000",
6951
- "720p": "https://v16m-default.tiktokcdn.com/4ee4e5763b088d7d77e4a9f4fce502b6/6a2b70c8/video/tos/maliva/tos-maliva-ve-0068c799-us/ooEipQa9HbhJ4ChzASIngUPhBAdXiABIvxU2E/?a=0&bti=NTU4QDM1NGA%3D&&bt=877&ft=cApXJCz7ThWHK-z9LGZmo0P&mime_type=video_mp4&rc=ZTg3OTQ0NTQzZGVpNWg6NkBpajQ8Zms5cjN1OzMzZzczNEBhNC0yMDViNi8xLV9hX2AuYSNkNm4uMmQ0bmJhLS1kMS9zcw%3D%3D&vvpl=1&l=20260612043527C18C959B9A8CF584D398&btag=e00090000"
6952
- },
6953
- "width": 720,
6954
- "height": 1280
6955
- }
7109
+ name: "GYMSHARK LTD",
7110
+ ids: "7078923208527618049",
6956
7111
  },
7112
+ ],
7113
+ ads: [
6957
7114
  {
6958
- "ad_title": "True Heroes go ALL IN or nothing. See yourself at the top!",
6959
- "brand_name": "",
6960
- "cost": 0,
6961
- "ctr": 0.29,
6962
- "favorite": false,
6963
- "id": "7640089122220736530",
6964
- "industry_key": "label_25100000000",
6965
- "is_search": true,
6966
- "like": 1115,
6967
- "objective_key": "campaign_objective_conversion",
6968
- "video_info": {
6969
- "vid": "v10033g50000d8jbia7og65q0198frmg",
6970
- "duration": 105.003,
6971
- "cover": "https://p16-common-sign.tiktokcdn.com/tos-alisg-p-0051c001-sg/o8jPFEKAAIYhaBUQ6CM5tAZiBiKaaAuSi7Hzm~tplv-noop.image?dr=18692&refresh_token=3750a204&x-expires=1781231832&x-signature=RfXRGuG8N6d69HxYz2Z9XUKgdWU%3D&t=9276707c&ps=14f1eb3e&shp=9e36835a&shcp=317596d8&idc=my2&VideoID=v10033g50000d8jbia7og65q0198frmg",
6972
- "video_url": {
6973
- "1080p": "https://v16m-default.tiktokcdn.com/3dad0efc22921436631456d0eb262abc/6a2b70d8/video/tos/alisg/tos-alisg-ve-0051c001-sg/oEPIgOBQUJpQBtqKOFyFDfEMODsYfUAzNhBAIQ/?a=0&bti=NTU4QDM1NGA%3D&&bt=2989&ft=cApXJCz7ThWHK-z9LGZmo0P&mime_type=video_mp4&rc=OzU3NTU5ZTxlaDs0NmRoaEBpanU7NHQ5cmRlOzMzODYzNEBjMjBhYl5eXy0xMjY0L2MtYSNqYzYtMmQ0ZmdhLS1kMC1zcw%3D%3D&vvpl=1&l=20260612043527C18C959B9A8CF584D398&btag=e00088000",
6974
- "360p": "https://v16m-default.tiktokcdn.com/6c204fed990c1083f8bbd68b500b660e/6a2b70d8/video/tos/alisg/tos-alisg-ve-0051c001-sg/oUYBAIDIFOzFBQOkIN1KABPDUsJQIQgfgqyOeE/?a=0&bti=NTU4QDM1NGA%3D&&bt=551&ft=cApXJCz7ThWHK-z9LGZmo0P&mime_type=video_mp4&rc=aDs3ZDRmNzM5OGg3NWZmOEBpanU7NHQ5cmRlOzMzODYzNEBgMS80NTAuXjQxXmBeYmNhYSNqYzYtMmQ0ZmdhLS1kMC1zcw%3D%3D&vvpl=1&l=20260612043527C18C959B9A8CF584D398&btag=e00088000",
6975
- "480p": "https://v16m-default.tiktokcdn.com/c4a6191ed579f76eaf7b6a6611966b3b/6a2b70d8/video/tos/alisg/tos-alisg-ve-0051c001-sg/okAEI5qKBEgFlH2AAniQo8mC5AfH1KAIiAwHBA/?a=0&bti=NTU4QDM1NGA%3D&&bt=780&ft=cApXJCz7ThWHK-z9LGZmo0P&mime_type=video_mp4&rc=ODRmZWk6NzU1NDU4OWQ3NUBpanU7NHQ5cmRlOzMzODYzNEAwNDAwNS4xXl8xMDZiYTMyYSNqYzYtMmQ0ZmdhLS1kMC1zcw%3D%3D&vvpl=1&l=20260612043527C18C959B9A8CF584D398&btag=e00088000",
6976
- "540p": "https://v16m-default.tiktokcdn.com/07591ee6ce0fc4ca315a41f1d87ee420/6a2b70d8/video/tos/alisg/tos-alisg-ve-0051c001-sg/oI2EoHAi5CI5ANF1AKQEmIHiqfs8qZBoABlAwn/?a=0&bti=NTU4QDM1NGA%3D&&bt=1063&ft=cApXJCz7ThWHK-z9LGZmo0P&mime_type=video_mp4&rc=ODZmPDQ5ZjY2NTw7NzQzOkBpanU7NHQ5cmRlOzMzODYzNEAuXmFjX2NhNjAxM140MzRiYSNqYzYtMmQ0ZmdhLS1kMC1zcw%3D%3D&vvpl=1&l=20260612043527C18C959B9A8CF584D398&btag=e00088000",
6977
- "720p": "https://v16m-default.tiktokcdn.com/1404645b61626339c2e1d4c6df4ebb12/6a2b70d8/video/tos/alisg/tos-alisg-ve-0051c001-sg/okYmBiwEIK1QnHBHEAHu5oiSHAlWIAf52RAxAC/?a=0&bti=NTU4QDM1NGA%3D&&bt=1460&ft=cApXJCz7ThWHK-z9LGZmo0P&mime_type=video_mp4&rc=aDs5O2lpNTg0Mzc2NGc8N0BpanU7NHQ5cmRlOzMzODYzNEA2YGNhYmMuXjIxLWBfMV9eYSNqYzYtMmQ0ZmdhLS1kMC1zcw%3D%3D&vvpl=1&l=20260612043527C18C959B9A8CF584D398&btag=e00088000"
7115
+ id: "1871655924410641",
7116
+ url: "https://library.tiktok.com/ads/detail/?ad_id=1871655924410641",
7117
+ name: "GYMSHARK LTD",
7118
+ audit_status: "1",
7119
+ type: "2",
7120
+ first_shown_date: 1784937600000,
7121
+ last_shown_date: 1785024000000,
7122
+ videos: [
7123
+ {
7124
+ video_url: "https://library.tiktok.com/api/v1/cdn/...",
7125
+ cover_img: "https://p16-common-sign.tiktokcdn.com/...",
6978
7126
  },
6979
- "width": 720,
6980
- "height": 1280
6981
- }
7127
+ ],
7128
+ estimated_audience: "1K-10K",
7129
+ spent: "",
7130
+ impression: 0,
7131
+ show_mode: 1,
7132
+ image_urls: [],
7133
+ rejection_info: null,
7134
+ sor_audit_status: "1",
6982
7135
  },
6983
7136
  ],
6984
- "pagination": {
6985
- "has_more": true,
6986
- "page": 1,
6987
- "size": 20,
6988
- "total_count": 326
6989
- },
6990
- "total": 326,
6991
- "has_more": true,
6992
- "cursor": 2
7137
+ total: 62344,
7138
+ has_more: true,
7139
+ cursor: "opaque cursor for the next page",
6993
7140
  },
7141
+ responseFields: [
7142
+ {
7143
+ path: "ads[].url",
7144
+ description: "Public TikTok Ads Library detail page for the ad.",
7145
+ },
7146
+ ],
6994
7147
  },
6995
7148
  {
6996
7149
  name: "Ad Library Ad",
6997
7150
  method: "GET",
6998
- description: "Gets details for a TikTok Creative Center Top Ad.",
7151
+ description: "Gets details for a TikTok ad from either Creative Center Top Ads or TikTok's public Ads Library.",
6999
7152
  fullDescription:
7000
- "Fetches one TikTok Creative Center Top Ad by material/ad ID or URL. Uses the same Creative Center data behind pages like ads.tiktok.com/business/creativecenter/topads/{id}/pc/en, including title, metrics, video info, landing page, country codes, objective, industry, source, the Creative Center URL, summary/analysis, interactive time analysis graph data, and recommended-for-you ads when TikTok provides them.",
7153
+ "Fetches one TikTok ad by ID or URL. It first checks Creative Center Top Ads (ads.tiktok.com), then TikTok's public transparency Ads Library (library.tiktok.com) when the ID is not a Top Ads material. Both sources return the same response shape. Fields TikTok does not expose for a public Ads Library ad are null, empty, or false as appropriate.",
7001
7154
  path: "/v1/tiktok/ad-library/ad",
7002
7155
  params: [
7003
7156
  {
7004
7157
  name: "ad_id",
7005
7158
  type: "string",
7006
7159
  required: true,
7007
- description: "TikTok Top Ads material/ad ID, or a Top Ads detail URL.",
7008
- placeholder: "7642386438915309575",
7160
+ description: "Creative Center Top Ads material ID or URL, or a public Ads Library ad ID or library.tiktok.com detail URL.",
7161
+ placeholder: "1869335220395266",
7009
7162
  },
7010
7163
  ],
7011
7164
  sampleResponse: {
@@ -7904,7 +8057,7 @@ export const apis = [
7904
8057
  method: "GET",
7905
8058
  description: "Search the LinkedIn Ad Library",
7906
8059
  fullDescription:
7907
- "Searches the LinkedIn Ad Library by company name, keyword, or companyId with optional country and date filters. Each ad includes id, description, headline, adType, advertiser, targeting details, image or video URLs, totalImpressions, and impressionsByCountry. Supports pagination via paginationToken.",
8060
+ "Searches the LinkedIn Ad Library by company name, keyword, or companyId with optional country and date filters. Custom date filtering requires both startDate and endDate. LinkedIn accepts dates from the date one year ago through yesterday. Each ad includes id, description, headline, adType, advertiser, targeting details, image or video URLs, totalImpressions, and impressionsByCountry. Date and impression fields are nullable when LinkedIn does not expose them on the public ad page. Supports pagination via paginationToken.",
7908
8061
  path: "/v1/linkedin/ads/search",
7909
8062
  sampleResponse: {
7910
8063
  success: true,
@@ -8004,15 +8157,17 @@ export const apis = [
8004
8157
  name: "startDate",
8005
8158
  type: "string",
8006
8159
  required: false,
8007
- description: "Start date to search for. Format: YYYY-MM-DD",
8008
- placeholder: "2024-01-01",
8160
+ description:
8161
+ "Start date in YYYY-MM-DD format. Must be used with endDate and cannot be earlier than the date one year ago.",
8162
+ placeholder: "2026-01-01",
8009
8163
  },
8010
8164
  {
8011
8165
  name: "endDate",
8012
8166
  type: "string",
8013
8167
  required: false,
8014
- description: "End date to search for. Format: YYYY-MM-DD",
8015
- placeholder: "2024-01-10",
8168
+ description:
8169
+ "End date in YYYY-MM-DD format. Must be used with startDate and cannot be today or a future date.",
8170
+ placeholder: "2026-09-01",
8016
8171
  },
8017
8172
  {
8018
8173
  name: "paginationToken",
@@ -8028,7 +8183,7 @@ export const apis = [
8028
8183
  method: "GET",
8029
8184
  description: "Get the details for an ad",
8030
8185
  fullDescription:
8031
- "Retrieves detailed information about a specific LinkedIn ad by URL. Returns id, description, headline, adType, advertiser, and targeting with language, location, and audience criteria. Also includes totalImpressions, impressionsByCountry, adDuration, startDate, and endDate.",
8186
+ "Retrieves detailed information about a specific LinkedIn ad by URL. Returns id, description, headline, adType, advertiser, and targeting with language, location, and audience criteria. Also includes totalImpressions, impressionsByCountry, adDuration, startDate, and endDate. Date and impression fields are nullable when LinkedIn does not expose them on the public ad page.",
8032
8187
  path: "/v1/linkedin/ad",
8033
8188
  params: [
8034
8189
  {
@@ -9130,119 +9285,43 @@ export const apis = [
9130
9285
  description:
9131
9286
  "Get recent posts from a subreddit with engagement metrics",
9132
9287
  fullDescription:
9133
- "Fetches posts from a subreddit with sorting and filtering options. Each post includes title, author, selftext, score, ups, upvote_ratio, num_comments, created_utc, url, permalink, subreddit_subscribers, and is_video. Supports sort (best, hot, new, top, rising), timeframe filtering, pagination via the after token, and a trim parameter for lighter responses.",
9288
+ "Fetches posts from a subreddit with sorting and filtering options. Each post includes title, author, link_flair_text when Reddit exposes it, selftext, score, ups, upvote_ratio, num_comments, created_utc, url, permalink, subreddit_subscribers, and is_video. Supports sort (best, hot, new, top, rising), timeframe filtering, pagination via the after token, and a trim parameter for lighter responses.",
9134
9289
  path: "/v1/reddit/subreddit",
9135
9290
  paginationField: "after",
9136
9291
  sampleResponse: {
9137
9292
  posts: [
9138
9293
  {
9139
- approved_at_utc: null,
9294
+ id: "1lfbo7u",
9295
+ author: "Vetro_Nodulare2",
9296
+ author_fullname: "t2_16syu27ar1",
9140
9297
  subreddit: "AskReddit",
9298
+ title: "What is a thing you love that lots of people hate?",
9299
+ link_flair_text: null,
9141
9300
  selftext: "",
9142
- author_fullname: "t2_aelahp9al",
9143
- saved: false,
9144
- mod_reason_title: null,
9145
- gilded: 0,
9146
- clicked: false,
9147
- title:
9148
- "What are your thoughts on California’s bill that would ban most law enforcement officers from wearing face masks while on duty?",
9149
- link_flair_richtext: [],
9150
- subreddit_name_prefixed: "r/AskReddit",
9151
- hidden: false,
9152
- pwls: 6,
9153
- link_flair_css_class: null,
9301
+ selftext_html: "",
9154
9302
  downs: 0,
9155
- top_awarded_type: null,
9156
- hide_score: false,
9157
- name: "t3_1ldr6b9",
9158
- quarantine: false,
9159
- link_flair_text_color: "dark",
9160
- upvote_ratio: 0.93,
9161
- author_flair_background_color: null,
9162
- subreddit_type: "public",
9163
- ups: 12606,
9303
+ name: "t3_1lfbo7u",
9304
+ upvote_ratio: 0.9,
9305
+ ups: 45,
9164
9306
  total_awards_received: 0,
9165
- media_embed: {},
9166
- author_flair_template_id: null,
9167
- is_original_content: false,
9168
- user_reports: [],
9169
- secure_media: null,
9170
- is_reddit_media_domain: false,
9171
- is_meta: false,
9172
- category: null,
9173
- secure_media_embed: {},
9174
- link_flair_text: null,
9175
- can_mod_post: false,
9176
- score: 12606,
9177
- approved_by: null,
9178
- is_created_from_ads_ui: false,
9179
- author_premium: false,
9180
- thumbnail: "",
9181
- edited: false,
9182
- author_flair_css_class: null,
9183
- author_flair_richtext: [],
9184
- gildings: {},
9185
- content_categories: null,
9186
- is_self: true,
9187
- mod_note: null,
9188
- created: 1750176516,
9189
- link_flair_type: "text",
9190
- wls: 6,
9191
- removed_by_category: null,
9192
- banned_by: null,
9193
- author_flair_type: "text",
9194
- domain: "self.AskReddit",
9195
- allow_live_comments: false,
9196
- selftext_html: null,
9197
- likes: null,
9198
- suggested_sort: null,
9199
- banned_at_utc: null,
9200
- view_count: null,
9201
- archived: false,
9202
- no_follow: false,
9203
- is_crosspostable: false,
9204
- pinned: false,
9307
+ score: 45,
9308
+ created: 1750341959,
9309
+ created_utc: 1750341959,
9310
+ created_at_iso: "2025-06-19T16:45:59.000Z",
9311
+ num_comments: 349,
9312
+ url: "https://www.reddit.com/r/AskReddit/comments/1lfbo7u/what_is_a_thing_you_love_that_lots_of_people_hate/",
9313
+ permalink:
9314
+ "/r/AskReddit/comments/1lfbo7u/what_is_a_thing_you_love_that_lots_of_people_hate/",
9315
+ subreddit_subscribers: null,
9316
+ is_video: false,
9205
9317
  over_18: false,
9206
- all_awardings: [],
9207
- awarders: [],
9208
- media_only: false,
9209
- can_gild: false,
9210
9318
  spoiler: false,
9211
- locked: false,
9212
- author_flair_text: null,
9213
- treatment_tags: [],
9214
- visited: false,
9215
- removed_by: null,
9216
- num_reports: null,
9217
- distinguished: null,
9319
+ domain: "self.AskReddit",
9218
9320
  subreddit_id: "t5_2qh1i",
9219
- author_is_blocked: false,
9220
- mod_reason_by: null,
9221
- removal_reason: null,
9222
- link_flair_background_color: "",
9223
- id: "1ldr6b9",
9224
- is_robot_indexable: true,
9225
- report_reasons: null,
9226
- author: "Ecstatic-Medium-6320",
9227
- discussion_type: null,
9228
- num_comments: 1921,
9229
- send_replies: false,
9230
- contest_mode: false,
9231
- mod_reports: [],
9232
- author_patreon_flair: false,
9233
- author_flair_text_color: null,
9234
- permalink:
9235
- "/r/AskReddit/comments/1ldr6b9/what_are_your_thoughts_on_californias_bill_that/",
9236
- stickied: false,
9237
- url: "https://www.reddit.com/r/AskReddit/comments/1ldr6b9/what_are_your_thoughts_on_californias_bill_that/",
9238
- subreddit_subscribers: 56098571,
9239
- created_utc: 1750176516,
9240
- num_crossposts: 1,
9241
- media: null,
9242
- is_video: false,
9321
+ post_hint: "text",
9243
9322
  },
9244
9323
  ],
9245
- after: "t3_1ld8q7h",
9324
+ after: "t3_1lfogps",
9246
9325
  },
9247
9326
  trimmedResponse: {
9248
9327
  posts: [
@@ -9252,6 +9331,9 @@ export const apis = [
9252
9331
  author_fullname: "t2_16syu27ar1",
9253
9332
  subreddit: "AskReddit",
9254
9333
  title: "What is a thing you love that lots of people hate?",
9334
+ link_flair_text: null,
9335
+ selftext: "",
9336
+ selftext_html: "",
9255
9337
  downs: 0,
9256
9338
  name: "t3_1lfbo7u",
9257
9339
  upvote_ratio: 0.9,
@@ -9272,6 +9354,9 @@ export const apis = [
9272
9354
  subreddit: "AskReddit",
9273
9355
  title:
9274
9356
  "What's the best physical pleasure you have ever experienced?",
9357
+ link_flair_text: null,
9358
+ selftext: "",
9359
+ selftext_html: "",
9275
9360
  downs: 0,
9276
9361
  name: "t3_1leoazg",
9277
9362
  upvote_ratio: 0.91,
@@ -9493,11 +9578,58 @@ export const apis = [
9493
9578
  },
9494
9579
  },
9495
9580
  {
9581
+ name: "Post",
9582
+ method: "GET",
9583
+ description: "Get information from a Reddit post without comments",
9584
+ fullDescription:
9585
+ "Retrieves public Reddit post details by URL without fetching or returning comments. Returns the text post body in selftext when present, plus the title, author, subreddit, score, upvote ratio, comment count, timestamps, permalink, and post flags. Accepts canonical Reddit post URLs and Reddit mobile share URLs.",
9586
+ path: "/v1/reddit/post",
9587
+ params: [
9588
+ {
9589
+ name: "url",
9590
+ type: "string",
9591
+ required: true,
9592
+ description: "Reddit post URL",
9593
+ placeholder:
9594
+ "https://www.reddit.com/r/webscraping/comments/1q6pxwn/just_started_web_scraping_is_this_a_good_start/",
9595
+ },
9596
+ ],
9597
+ sampleResponse: {
9598
+ id: "1q6pxwn",
9599
+ author: "franik33",
9600
+ author_fullname: "t2_16xbknfp71",
9601
+ subreddit: "webscraping",
9602
+ title: "Just Started Web Scraping — Is This a Good Start?",
9603
+ selftext:
9604
+ "Hi everyone, I started getting into web scraping about 3–4 days ago. I already have some solid experience with Python, and my first scraping project was a public website. I managed to collect around 7,000 records and everything worked as expected. I’m curious whether this is considered a decent start for someone new to scraping, or if it’s fairly basic stuff.Also, I’d like to hear honest opinions: is web scraping still worth investing time in today (for projects, automation, or monetization), or is it becoming a waste of time due to market saturation and restrictions? Any real-world experiences or insights would be appreciated. Thanks in advance.",
9605
+ downs: 0,
9606
+ name: "t3_1q6pxwn",
9607
+ upvote_ratio: 0.9230769230769231,
9608
+ ups: 33,
9609
+ total_awards_received: 0,
9610
+ score: 33,
9611
+ created: 1767816090,
9612
+ created_utc: 1767816090,
9613
+ created_at_iso: "2026-01-07T20:01:30.000Z",
9614
+ num_comments: 53,
9615
+ url: "https://www.reddit.com/r/webscraping/comments/1q6pxwn/just_started_web_scraping_is_this_a_good_start/",
9616
+ permalink:
9617
+ "/r/webscraping/comments/1q6pxwn/just_started_web_scraping_is_this_a_good_start/",
9618
+ subreddit_subscribers: null,
9619
+ is_video: false,
9620
+ archived: true,
9621
+ locked: false,
9622
+ over_18: false,
9623
+ spoiler: false,
9624
+ },
9625
+ },
9626
+ ...withPostVariant({
9496
9627
  name: "Post Comments",
9497
9628
  method: "GET",
9498
- description: "Get comments + post information from a Reddit post",
9629
+ description:
9630
+ "Get comments and post information from a Reddit post. Pass one opaque cursor returned by the previous response to get the next page. Cursor batching is not supported. Use POST with the same JSON-body parameters if a cursor becomes too large for a GET URL.",
9499
9631
  fullDescription:
9500
- "Retrieves comments and post details from a Reddit post by URL. Returns the post with title, author, score, ups, upvote_ratio, num_comments, and created_utc, plus a comments array where each comment includes author, body, body_html, score, created_utc, parent_id, permalink, and nested replies. Supports cursor-based pagination for loading more comments and a trim parameter for lighter responses.",
9632
+ "Retrieves comments and post details from a Reddit post by URL. Returns the post with title, author, score, ups, upvote_ratio, num_comments, and created_utc, plus a comments array where each comment includes author, body, body_html, score, created_utc, parent_id, permalink, and nested replies. Both GET and POST are supported. Use GET for normal requests. Pass one opaque cursor exactly as returned by more.cursor or replies.more.cursor to load the next page. Cursor batching and comma-separated cursor values are not supported. If an opaque cursor becomes too large after extensive pagination, use POST and send the same parameters in the JSON body. Supports cursor-based pagination for loading more comments and a trim parameter for lighter responses.",
9501
9633
  path: "/v1/reddit/post/comments",
9502
9634
  params: [
9503
9635
  {
@@ -9512,8 +9644,8 @@ export const apis = [
9512
9644
  name: "cursor",
9513
9645
  type: "string",
9514
9646
  required: false,
9515
- description: "Cursor to get more comments, or replies.",
9516
- placeholder: "ed1lvsa,ed3fnpq,ed25l2w",
9647
+ description: "One opaque cursor returned by the previous response to get more comments or replies. Do not combine multiple cursors.",
9648
+ placeholder: "opaque_cursor_returned_by_previous_response",
9517
9649
  },
9518
9650
  {
9519
9651
  name: "trim",
@@ -10671,10 +10803,10 @@ export const apis = [
10671
10803
  ],
10672
10804
  more: {
10673
10805
  has_more: true,
10674
- cursor: "ed1jhoi,ed1f3kw,ed1qgjh,ed1e4vd,ed1benx",
10806
+ cursor: "opaque_cursor_returned_by_previous_response",
10675
10807
  },
10676
10808
  },
10677
- },
10809
+ }),
10678
10810
  // {
10679
10811
  // name: "Simple Comments",
10680
10812
  // method: "GET",
@@ -10857,9 +10989,9 @@ export const apis = [
10857
10989
  {
10858
10990
  name: "Search",
10859
10991
  method: "GET",
10860
- description: "Search Reddit for posts",
10992
+ description: "Search Reddit for posts or comments",
10861
10993
  fullDescription:
10862
- "Searches across all of Reddit for posts matching a query. Each post includes title, author, selftext, subreddit, score, ups, upvote_ratio, num_comments, created_utc, url, permalink, and is_video. Supports sort (relevance, new, top, comment_count), timeframe filtering, pagination via the after token, and a trim parameter for lighter responses.",
10994
+ "Searches across all of Reddit for posts or comments matching a query. Set filter to posts (the default) or comments. Post results include title, author, selftext, subreddit, score, ups, upvote_ratio, num_comments, created_utc, url, permalink, and is_video. Comment results include the matching body, author, votes, timestamps, comment URL, parent relationship, and post/subreddit context. Comment searches support relevance, new, and top sorting. Timeframe filtering applies to post searches. Pagination uses the after token, and trim returns a lighter response.",
10863
10995
  path: "/v1/reddit/search",
10864
10996
  paginationField: "after",
10865
10997
  params: [
@@ -10869,11 +11001,20 @@ export const apis = [
10869
11001
  required: true,
10870
11002
  description: "Search query",
10871
11003
  },
11004
+ {
11005
+ name: "filter",
11006
+ type: "select",
11007
+ required: false,
11008
+ description: "Search posts or comments",
11009
+ placeholder: "posts",
11010
+ options: ["posts", "comments"],
11011
+ },
10872
11012
  {
10873
11013
  name: "sort",
10874
11014
  type: "select",
10875
11015
  required: false,
10876
- description: "Sort by",
11016
+ description:
11017
+ "Sort by. Comment search supports relevance, new, and top; comment_count is for post search only.",
10877
11018
  placeholder: "relevance",
10878
11019
  options: ["relevance", "new", "top", "comment_count"],
10879
11020
  },
@@ -10881,7 +11022,7 @@ export const apis = [
10881
11022
  name: "timeframe",
10882
11023
  type: "select",
10883
11024
  required: false,
10884
- description: "Timeframe",
11025
+ description: "Post search timeframe",
10885
11026
  placeholder: "all",
10886
11027
  options: ["all", "day", "week", "month", "year"],
10887
11028
  },
@@ -11829,7 +11970,7 @@ export const apis = [
11829
11970
  method: "GET",
11830
11971
  description: "Get Truth Social post",
11831
11972
  fullDescription:
11832
- "Fetches a single Truth Social post by URL, returning text, id, created_at, url, content, account details, media_attachments, card link previews, replies_count, reblogs_count, and favourites_count. Only posts from prominent public figures (e.g., Trump, Vance) are accessible without authentication.",
11973
+ "Fetches a single Truth Social post by URL, returning text, id, created_at, url, content, account details, media_attachments, card link previews, replies_count, reblogs_count, and favourites_count. Set download_media=true to download attached images or video and return permanent Supabase URLs. Only posts from prominent public figures (e.g., Trump, Vance) are accessible without authentication.",
11833
11974
  path: "/v1/truthsocial/post",
11834
11975
  params: [
11835
11976
  {
@@ -11840,6 +11981,15 @@ export const apis = [
11840
11981
  placeholder:
11841
11982
  "https://truthsocial.com/@realDonaldTrump/posts/114315219437063160",
11842
11983
  },
11984
+ {
11985
+ name: "download_media",
11986
+ type: "boolean",
11987
+ required: false,
11988
+ description:
11989
+ "Set to true to download the attached video/images and get back permanent Supabase URLs. Costs 10 credits if media is found, 1 credit otherwise.",
11990
+ placeholder: false,
11991
+ credits: 10,
11992
+ },
11843
11993
  ],
11844
11994
  sampleResponse: {
11845
11995
  success: true,
@@ -14645,7 +14795,7 @@ export const apis = [
14645
14795
  method: "GET",
14646
14796
  description: "Search Google",
14647
14797
  fullDescription:
14648
- "Performs a Google search and returns organic results with url, title, and description for each result. Supports an optional region parameter (2-letter country code) to get localized results from a specific country.",
14798
+ "Performs a Google search and returns organic results with url, title, and description for each result. Supports an optional region parameter (2-letter country code) to get localized results from a specific country. Pages 1 through 11 are supported; requests for page 12 or greater return a 400 response.",
14649
14799
  path: "/v1/google/search",
14650
14800
  params: [
14651
14801
  {
@@ -14675,7 +14825,7 @@ export const apis = [
14675
14825
  name: "page",
14676
14826
  type: "number",
14677
14827
  required: false,
14678
- description: "Page number to retrieve",
14828
+ description: "Page number to retrieve. Must be between 1 and 11; page 12 or greater returns a 400 response.",
14679
14829
  placeholder: "1",
14680
14830
  }
14681
14831
  ],
@@ -17662,10 +17812,206 @@ export const apis = [
17662
17812
  },
17663
17813
  ],
17664
17814
  },
17815
+ {
17816
+ id: "apple-music",
17817
+ name: "Apple Music",
17818
+ description: "Scrape Apple Music artists, songs, albums, and search results",
17819
+ endpoints: [
17820
+ {
17821
+ name: "Artist",
17822
+ method: "GET",
17823
+ description: "Get Apple Music artist",
17824
+ fullDescription:
17825
+ "Retrieves public Apple Music artist details, including artwork, editorial notes, top songs, albums, music videos, playlists, and related sections.",
17826
+ path: "/v1/apple-music/artist",
17827
+ params: [
17828
+ {
17829
+ name: "id",
17830
+ type: "string",
17831
+ required: false,
17832
+ description: "Apple Music artist id. If you'd prefer to use the URL instead, you can use the url parameter instead.",
17833
+ placeholder: "159260351",
17834
+ },
17835
+ {
17836
+ name: "url",
17837
+ type: "string",
17838
+ required: false,
17839
+ description: "Apple Music artist URL. If you'd prefer to use the id instead, you can use the id parameter instead.",
17840
+ placeholder: "https://music.apple.com/us/artist/taylor-swift/159260351",
17841
+ },
17842
+ ],
17843
+ sampleResponse: {
17844
+ success: true,
17845
+ credits_remaining: 49996588524,
17846
+ data: {
17847
+ id: "159260351",
17848
+ kind: "artist",
17849
+ name: "Taylor Swift",
17850
+ url: "https://music.apple.com/us/artist/taylor-swift/159260351",
17851
+ artwork: {
17852
+ url: "https://is1-ssl.mzstatic.com/image/thumb/AMCArtistImages221/v4/70/30/3b/example/1200x1200bb.jpg",
17853
+ width: 5998,
17854
+ height: 5998,
17855
+ },
17856
+ editorial_notes: "The country world feigned surprise when Taylor Swift formally embraced pop...",
17857
+ top_songs: [
17858
+ {
17859
+ id: "1833328840",
17860
+ kind: "song",
17861
+ title: "The Fate of Ophelia",
17862
+ artist_name: "Taylor Swift",
17863
+ url: "https://music.apple.com/us/album/the-fate-of-ophelia/1833328839?i=1833328840",
17864
+ duration_ms: 226000,
17865
+ },
17866
+ ],
17867
+ albums: [
17868
+ {
17869
+ id: "1468058165",
17870
+ kind: "album",
17871
+ title: "Lover",
17872
+ subtitle: "Taylor Swift",
17873
+ track_count: 18,
17874
+ url: "https://music.apple.com/us/album/lover/1468058165",
17875
+ },
17876
+ ],
17877
+ },
17878
+ },
17879
+ },
17880
+ {
17881
+ name: "Album",
17882
+ method: "GET",
17883
+ description: "Get Apple Music album",
17884
+ fullDescription:
17885
+ "Retrieves public Apple Music album details, including title, artist, artwork, release info, tracks, and more by the artist.",
17886
+ path: "/v1/apple-music/album",
17887
+ params: [
17888
+ {
17889
+ name: "id",
17890
+ type: "string",
17891
+ required: false,
17892
+ description: "Apple Music album id. If you'd prefer to use the URL instead, you can use the url parameter instead.",
17893
+ placeholder: "1468058165",
17894
+ },
17895
+ {
17896
+ name: "url",
17897
+ type: "string",
17898
+ required: false,
17899
+ description: "Apple Music album URL. If you'd prefer to use the id instead, you can use the id parameter instead.",
17900
+ placeholder: "https://music.apple.com/us/album/lover/1468058165",
17901
+ },
17902
+ ],
17903
+ sampleResponse: {
17904
+ success: true,
17905
+ credits_remaining: 49996588523,
17906
+ data: {
17907
+ id: "1468058165",
17908
+ kind: "album",
17909
+ title: "Lover",
17910
+ artist_name: "Taylor Swift",
17911
+ artist_url: "https://music.apple.com/us/artist/taylor-swift/159260351",
17912
+ url: "https://music.apple.com/us/album/lover/1468058165",
17913
+ track_count: 18,
17914
+ release_info: "August 23, 2019\n18 songs, 1 hour 1 minute\n℗ 2019 Taylor Swift",
17915
+ tracks: [
17916
+ {
17917
+ id: "1468058169",
17918
+ kind: "song",
17919
+ title: "I Forgot That You Existed",
17920
+ duration_ms: 170651,
17921
+ track_number: 1,
17922
+ album_id: "1468058165",
17923
+ },
17924
+ ],
17925
+ },
17926
+ },
17927
+ },
17928
+ {
17929
+ name: "Track",
17930
+ method: "GET",
17931
+ description: "Get Apple Music track",
17932
+ fullDescription:
17933
+ "Retrieves public Apple Music song details by id or URL. Album track URLs with an i= song id are supported.",
17934
+ path: "/v1/apple-music/track",
17935
+ params: [
17936
+ {
17937
+ name: "id",
17938
+ type: "string",
17939
+ required: false,
17940
+ description: "Apple Music song id. Some songs have standalone song URLs; for album tracks, use the url parameter.",
17941
+ placeholder: "1833328840",
17942
+ },
17943
+ {
17944
+ name: "url",
17945
+ type: "string",
17946
+ required: false,
17947
+ description: "Apple Music song URL or album track URL.",
17948
+ placeholder: "https://music.apple.com/us/album/lover/1468058165?i=1468058169",
17949
+ },
17950
+ ],
17951
+ sampleResponse: {
17952
+ success: true,
17953
+ credits_remaining: 49996588522,
17954
+ data: {
17955
+ id: "1468058169",
17956
+ kind: "song",
17957
+ title: "I Forgot That You Existed",
17958
+ album: null,
17959
+ url: "https://music.apple.com/us/album/i-forgot-that-you-existed/1468058165?i=1468058169",
17960
+ duration_ms: 170651,
17961
+ track_number: 1,
17962
+ artist_name: null,
17963
+ explicit: false,
17964
+ },
17965
+ },
17966
+ },
17967
+ {
17968
+ name: "Search",
17969
+ method: "GET",
17970
+ description: "Search Apple Music",
17971
+ fullDescription:
17972
+ "Searches Apple Music and returns public result sections for artists, albums, songs, playlists, stations, and music videos. Use type=song, album, artist, playlist, or all.",
17973
+ path: "/v1/apple-music/search",
17974
+ params: [
17975
+ {
17976
+ name: "query",
17977
+ type: "string",
17978
+ required: true,
17979
+ description: "Search query",
17980
+ placeholder: "taylor swift",
17981
+ },
17982
+ {
17983
+ name: "type",
17984
+ type: "string",
17985
+ required: false,
17986
+ description: "Result type to return. Use all, song, album, artist, playlist, station, music_video, or radio_episode.",
17987
+ placeholder: "song",
17988
+ },
17989
+ ],
17990
+ sampleResponse: {
17991
+ success: true,
17992
+ credits_remaining: 49996588521,
17993
+ data: {
17994
+ query: "taylor swift",
17995
+ type: "song",
17996
+ results: [
17997
+ {
17998
+ id: "1833328840",
17999
+ kind: "song",
18000
+ title: "The Fate of Ophelia",
18001
+ artist_name: "Taylor Swift",
18002
+ url: "https://music.apple.com/us/album/the-fate-of-ophelia/1833328839?i=1833328840",
18003
+ duration_ms: 226000,
18004
+ },
18005
+ ],
18006
+ },
18007
+ },
18008
+ },
18009
+ ],
18010
+ },
17665
18011
  {
17666
18012
  id: "spotify",
17667
18013
  name: "Spotify",
17668
- description: "Scrape Spotify artists, songs, and albums",
18014
+ description: "Scrape Spotify artists, songs, albums, playlists, and podcasts",
17669
18015
  endpoints: [
17670
18016
  {
17671
18017
  name: "Artist",
@@ -29686,6 +30032,89 @@ export const apis = [
29686
30032
  ]
29687
30033
  },
29688
30034
  },
30035
+ {
30036
+ name: "Playlist",
30037
+ method: "GET",
30038
+ description: "Get a Spotify playlist and its tracks",
30039
+ fullDescription:
30040
+ "Retrieves public Spotify playlist metadata and up to 50 tracks by playlist id or URL. For playlists with more tracks, pass the returned cursor into the next request until cursor is null.",
30041
+ path: "/v1/spotify/playlist",
30042
+ params: [
30043
+ {
30044
+ name: "id",
30045
+ type: "string",
30046
+ required: false,
30047
+ description: "Spotify playlist id. If you'd prefer to use the URL instead, you can use the url parameter instead.",
30048
+ placeholder: "37i9dQZF1DX4UtSsGT1Sbe",
30049
+ },
30050
+ {
30051
+ name: "url",
30052
+ type: "string",
30053
+ required: false,
30054
+ description: "Spotify playlist URL. If you'd prefer to use the id instead, you can use the id parameter instead.",
30055
+ placeholder: "https://open.spotify.com/playlist/37i9dQZF1DX4UtSsGT1Sbe",
30056
+ },
30057
+ {
30058
+ name: "cursor",
30059
+ type: "string",
30060
+ required: false,
30061
+ description: "Cursor returned by the previous response. Omit it for the first page.",
30062
+ placeholder: "50",
30063
+ },
30064
+ ],
30065
+ sampleResponse: {
30066
+ "success": true,
30067
+ "credits_remaining": 100,
30068
+ "id": "37i9dQZF1DX4UtSsGT1Sbe",
30069
+ "uri": "spotify:playlist:37i9dQZF1DX4UtSsGT1Sbe",
30070
+ "__typename": "Playlist",
30071
+ "description": "The biggest songs of the 1980s. Cover: Madonna",
30072
+ "followers": 12016730,
30073
+ "images": [
30074
+ {
30075
+ "sources": [
30076
+ {
30077
+ "height": null,
30078
+ "url": "https://i.scdn.co/image/ab67706f00000002fb8e01f2c022ab1a32e2c5a0",
30079
+ "width": null,
30080
+ },
30081
+ ],
30082
+ },
30083
+ ],
30084
+ "name": "All Out 80s",
30085
+ "ownerV2": {
30086
+ "__typename": "User",
30087
+ "name": "Spotify",
30088
+ "uri": "spotify:user:spotify",
30089
+ "username": "spotify",
30090
+ },
30091
+ "tracks": [
30092
+ {
30093
+ "id": "6r8k1vznHrzlEKYxL4dZEe",
30094
+ "uri": "spotify:track:6r8k1vznHrzlEKYxL4dZEe",
30095
+ "name": "La Isla Bonita",
30096
+ "albumOfTrack": {
30097
+ "name": "True Blue",
30098
+ "uri": "spotify:album:6fmnT17jc2Sc69q3nza1eD",
30099
+ },
30100
+ "artists": [
30101
+ {
30102
+ "profile": {
30103
+ "name": "Madonna",
30104
+ },
30105
+ "uri": "spotify:artist:6tbjWDEIzxoDsBA1FuhfPW",
30106
+ },
30107
+ ],
30108
+ "duration": {
30109
+ "totalMilliseconds": 242733,
30110
+ },
30111
+ "playcount": 785646615,
30112
+ },
30113
+ ],
30114
+ "cursor": 50,
30115
+ "totalCount": 150,
30116
+ },
30117
+ },
29689
30118
  {
29690
30119
  name: "Search",
29691
30120
  method: "GET",
@@ -32487,7 +32916,7 @@ export const apis = [
32487
32916
  {
32488
32917
  id: "snapchat",
32489
32918
  name: "Snapchat",
32490
- description: "Scrape Snapchat user profiles and thier stories",
32919
+ description: "Scrape Snapchat user profiles and their stories",
32491
32920
  endpoints: [
32492
32921
  {
32493
32922
  name: "User Profile",
@@ -32845,6 +33274,267 @@ export const apis = [
32845
33274
  },
32846
33275
  ],
32847
33276
  },
33277
+ {
33278
+ name: "Spotlight by Link",
33279
+ method: "GET",
33280
+ description: "Get Snapchat Spotlight video data by URL",
33281
+ fullDescription:
33282
+ "Fetches public data for a Snapchat Spotlight video by URL. Returns the snap id, description, creator, engagement counts, thumbnail, and content URL when Snapchat exposes them publicly.",
33283
+ path: "/v1/snapchat/spotlight",
33284
+ sampleResponse: {
33285
+ success: true,
33286
+ credits_remaining: 49997863208,
33287
+ spotlight: {
33288
+ snapId:
33289
+ "W7_EDlXWTBiXAEEniNoMPwAAYY2pvZnd0ZXVmAZ8fgG8pAZ8ff-_IAAAAAQ",
33290
+ storyId:
33291
+ "W7_EDlXWTBiXAEEniNoMPwAAYY2pvZnd0ZXVmAZ8fgG8pAZ8ff-_IAAAAAQ",
33292
+ description:
33293
+ "This is genuinely heartbreaking 💔 #relationship#funny#brainrot",
33294
+ llmTitle: null,
33295
+ llmDescription: null,
33296
+ viewCount: 251845,
33297
+ shareCount: 3807,
33298
+ commentCount: 803,
33299
+ engagementStats: {
33300
+ viewCount: 251845,
33301
+ shareCount: 3807,
33302
+ commentCount: 803,
33303
+ boostCount: 16203,
33304
+ recommendCount: 2670,
33305
+ },
33306
+ creator: {
33307
+ $case: "personCreator",
33308
+ personCreator: {
33309
+ username: "lilah4823",
33310
+ url: "https://www.snapchat.com/@lilah4823",
33311
+ name: "lilah",
33312
+ followerCount: "0",
33313
+ websiteUrl: "",
33314
+ },
33315
+ },
33316
+ durationMs: 56939,
33317
+ width: 540,
33318
+ height: 960,
33319
+ uploadDateMs: 1782915537473,
33320
+ thumbnailUrl:
33321
+ "https://cf-st.sc-cdn.net/d/TXqor3n6nwYvf2nDyAVlN.256.IRZXSOY?mo=GkcaDRoAGgAyAQRIA1AuYAFaEERmTGFyZ2VUaHVtYm5haWyiARAIgAIiCxIAKgdJUlpYU09ZogEQCJoKIgsSACoHSVJaWFNPWQ%3D%3D&uc=46",
33322
+ contentUrl:
33323
+ "https://cf-st.sc-cdn.net/d/TXqor3n6nwYvf2nDyAVlN.1034.IRZXSOY?mo=GkAaDRoAGgAyAQRIA1AuYAGiAS4IiggSHAoaIAFKEQoMY0Y9R0RFR0M5OU8uEPQDWgMQsz8iCxIAKgdJUlpYU09Z&uc=46",
33324
+ raw: {},
33325
+ },
33326
+ linkPreview: {},
33327
+ pageMetadata: {},
33328
+ videoMetadata: {},
33329
+ },
33330
+ params: [
33331
+ {
33332
+ name: "url",
33333
+ type: "string",
33334
+ required: true,
33335
+ description: "Snapchat Spotlight URL.",
33336
+ placeholder:
33337
+ "https://www.snapchat.com/@lilah4823/spotlight/W7_EDlXWTBiXAEEniNoMPwAAYY2pvZnd0ZXVmAZ8fgG8pAZ8ff-_IAAAAAQ",
33338
+ },
33339
+ ],
33340
+ },
33341
+ {
33342
+ name: "Spotlight Comments by Link",
33343
+ method: "GET",
33344
+ description: "Get comments from a Snapchat Spotlight URL",
33345
+ fullDescription:
33346
+ "Fetches public comments from Snapchat's Spotlight comments API by URL. Returns the snap id, comments, a cursor for the next page, and hasMore. Pass the returned cursor back as the cursor param to load more comments.",
33347
+ path: "/v1/snapchat/spotlight/comments",
33348
+ sampleResponse: {
33349
+ success: true,
33350
+ credits_remaining: 49997863207,
33351
+ snapId:
33352
+ "W7_EDlXWTBiXAEEniNoMPwAAYY2pvZnd0ZXVmAZ8fgG8pAZ8ff-_IAAAAAQ",
33353
+ comments: [
33354
+ {
33355
+ replyText:
33356
+ "Guys who can't even read a paragraph are hilarious 😭 get yourself a better man",
33357
+ replyPosterDisplayName: "🎸Callie✌️",
33358
+ replyTimestampMs: "1782948905027",
33359
+ threadedReplyCount: 152,
33360
+ reactCounts: [
33361
+ {
33362
+ reactTypeId: 1,
33363
+ reactCount: 829,
33364
+ },
33365
+ ],
33366
+ },
33367
+ ],
33368
+ cursor:
33369
+ "CpMCEpACQ3NjQkNnZ0tBbkp6RWdJSUJBb05DZ0owY3hJSENLZjA1TW55TXhLbkFXb1hjMzVrWld4MFlTMW1iM0pqWlMxdVlXMDFMWEJ5YjJSeWl3RUxFaEJUY0c5MGJHbG5hSFJTWlhCc2FXVnpJanRYTjE5RlJHeFlWMVJDYVZoQlJVVnVhVTV2VFZCM1FVRlpXVEp3ZGxwdVpEQmFXRlp0UVZvNFptZEhPSEJCV2pobVppMWZTVUZCUVVGQlVRd0xFaEJUY0c5MGJHbG5hSFJTWlhCc2FXVnpJaVJpWkRKaU1XSTNNeTAzWkRCa0xUUXlOV010T0dKbU1DMDBNVFU1T0RneU1XSTRNekVNR0FBZ0FRPT0SgwISgAJDcjBCQ2cwS0FuUnpFZ2NJNi1LODhmUXpFcWNCYWhkemZtUmxiSFJoTFdadmNtTmxMVzVoYlRVdGNISnZaSEtMQVFzU0VGTndiM1JzYVdkb2RGSmxjR3hwWlhNaU8xYzNYMFZFYkZoWFZFSnBXRUZGUlc1cFRtOU5VSGRCUVZsWk1uQjJXbTVrTUZwWVZtMUJXamhtWjBjNGNFRmFPR1ptTFY5SlFVRkJRVUZSREFzU0VGTndiM1JzYVdkb2RGSmxjR3hwWlhNaUpEYzFNbVZqWWpObUxUSmhZMkV0TkdVM1l5MDVaakF6TFdZNFpUVm1ZVEZrTmpVNVlnd1lBQ0FC",
33370
+ hasMore: true,
33371
+ },
33372
+ params: [
33373
+ {
33374
+ name: "url",
33375
+ type: "string",
33376
+ required: true,
33377
+ description: "Snapchat Spotlight URL.",
33378
+ placeholder:
33379
+ "https://www.snapchat.com/@lilah4823/spotlight/W7_EDlXWTBiXAEEniNoMPwAAYY2pvZnd0ZXVmAZ8fgG8pAZ8ff-_IAAAAAQ",
33380
+ },
33381
+ {
33382
+ name: "cursor",
33383
+ type: "string",
33384
+ required: false,
33385
+ description: "Pagination cursor from the previous response.",
33386
+ placeholder:
33387
+ "CpMCEpACQ3NjQkNnZ0tBbkp6RWdJSUJBb05DZ0owY3hJSENLZjA1TW55...",
33388
+ },
33389
+ ],
33390
+ },
33391
+ ],
33392
+ },
33393
+ {
33394
+ id: "creator-tools",
33395
+ name: "Creator Tools",
33396
+ description: "Tools for finding and analyzing creator profiles",
33397
+ endpoints: [
33398
+ {
33399
+ name: "Find Social Profiles",
33400
+ method: "GET",
33401
+ description:
33402
+ "Enter a creator's handle from one social media platform and get all of their social profiles.",
33403
+ fullDescription:
33404
+ "Accepts a supported platform and creator handle, validates both using platform-specific rules, and constructs the canonical source profile URL internally. URLs are not accepted as handles. Supported platforms are Instagram, TikTok, YouTube, X/Twitter, and Facebook; X is accepted as an alias for Twitter. YouTube accepts handles and 24-character channel IDs. The endpoint returns social profiles explicitly linked from the source profile and expands recognized link-in-bio pages. It also re-scrapes up to three supported profiles explicitly linked by the source and follows up to three unique public website URLs declared by the source or those trusted profiles for one page, while preserving each declared path and query. Generic service-provider landing pages reached through parked or unconfigured branded-domain redirects are ignored so the provider's own footer links are not attributed to the creator. It also checks whether the same handle exists on the other supported platforms. All attempted same-handle URLs are returned in same_handle_candidate_urls even when they cannot be verified strongly enough for profiles. Same-handle accounts are included in profiles only when corroborated by a shared owner-controlled website or a reciprocal profile link; matching handles and display names alone are not identity proof. same_handle_match records supporting name evidence at 0.75 confidence, while shared_website and website_link use 0.9. A bounded Google search discovers alternate handles, but Google results are never returned without verification. At most two candidates per other supported platform, up to four total, are re-scraped through that platform's profile scraper. The endpoint may also follow up to two unique recognized link-in-bio URLs declared by the re-scraped Google candidates. The global two-page cap is applied after candidates whose returned handles do not match their Google URLs are rejected. Optional profile probes and page fetches make one attempt and receive the shared enrichment abort signal. A reciprocal source-profile link found there verifies the candidate, and the page's explicit cross-platform profiles can then expand the verified identity graph. Google URLs that re-scrape to the same returned platform handle are deduplicated. A different-handle candidate is accepted only when it links back to the source profile, or when its normalized display name matches and it declares the same owner-controlled public website; common multi-tenant profile and storefront hosts are excluded from shared-website identity evidence. Google discovery uses google_search_match at 0.6, exact names use display_name_match at 0.75, reciprocal links use 0.95, and cross-platform social links explicitly declared by a verified candidate use verified_profile_link at 0.95. Source-linked URLs and failures are returned in source_linked_profile_urls and failed_source_linked_profile_urls. Google candidate URLs, candidate-declared link-in-bio URLs, verified URLs, and failures are returned in google_candidate_urls, google_candidate_link_in_bio_urls, verified_google_candidate_urls, failed_google_candidate_urls, and failed_google_candidate_link_in_bio_urls. Results are deterministic and do not use AI. Mixed or unreachable enrichment results are reported through partial and the matching failure fields. If every declared link-in-bio page fails and no other enrichment finds a profile, the request returns an uncharged 503. A successful live lookup costs 10 credits.",
33405
+ path: "/v1/find-social-profiles",
33406
+ credits: 10,
33407
+ params: [
33408
+ {
33409
+ name: "platform",
33410
+ type: "select",
33411
+ required: true,
33412
+ description: "Source social platform",
33413
+ options: [
33414
+ "instagram",
33415
+ "tiktok",
33416
+ "youtube",
33417
+ "x",
33418
+ "twitter",
33419
+ "facebook",
33420
+ ],
33421
+ placeholder: "instagram",
33422
+ },
33423
+ {
33424
+ name: "handle",
33425
+ type: "string",
33426
+ required: true,
33427
+ description:
33428
+ "Creator handle without a profile URL. A leading @ is optional.",
33429
+ placeholder: "creator",
33430
+ },
33431
+ ],
33432
+ sampleResponse: {
33433
+ source: {
33434
+ platform: "instagram",
33435
+ handle: "creator",
33436
+ url: "https://www.instagram.com/creator",
33437
+ },
33438
+ profiles: [
33439
+ {
33440
+ platform: "instagram",
33441
+ handle: "creator",
33442
+ url: "https://www.instagram.com/creator",
33443
+ confidence: 1,
33444
+ evidence: [
33445
+ "source_profile",
33446
+ "link_in_bio",
33447
+ "verified_profile_link",
33448
+ ],
33449
+ },
33450
+ {
33451
+ platform: "youtube",
33452
+ handle: "creator",
33453
+ url: "https://www.youtube.com/@creator",
33454
+ confidence: 0.9,
33455
+ evidence: [
33456
+ "same_handle_match",
33457
+ "shared_website",
33458
+ "website_link",
33459
+ ],
33460
+ },
33461
+ {
33462
+ platform: "tiktok",
33463
+ handle: "creator",
33464
+ url: "https://www.tiktok.com/@creator",
33465
+ confidence: 1,
33466
+ evidence: ["link_in_bio"],
33467
+ },
33468
+ {
33469
+ platform: "facebook",
33470
+ handle: "creator-page",
33471
+ url: "https://www.facebook.com/creator-page",
33472
+ confidence: 0.95,
33473
+ evidence: [
33474
+ "google_search_match",
33475
+ "display_name_match",
33476
+ "reciprocal_profile_link",
33477
+ ],
33478
+ },
33479
+ {
33480
+ platform: "linkedin",
33481
+ handle: "creator",
33482
+ url: "https://www.linkedin.com/in/creator",
33483
+ confidence: 0.95,
33484
+ evidence: ["verified_profile_link"],
33485
+ },
33486
+ ],
33487
+ link_in_bio_urls: ["https://linktr.ee/creator"],
33488
+ expanded_website_urls: ["https://creator.com/"],
33489
+ source_linked_profile_urls: ["https://x.com/creator"],
33490
+ failed_source_linked_profile_urls: [],
33491
+ same_handle_candidate_urls: [
33492
+ "https://www.tiktok.com/@creator",
33493
+ "https://www.youtube.com/@creator",
33494
+ ],
33495
+ partial: false,
33496
+ failed_link_in_bio_urls: [],
33497
+ failed_website_urls: [],
33498
+ same_handle_search_partial: false,
33499
+ google_search_used: true,
33500
+ google_search_failed: false,
33501
+ google_candidate_urls: [
33502
+ "https://www.facebook.com/creator-page",
33503
+ ],
33504
+ google_candidate_link_in_bio_urls: [
33505
+ "https://linktr.ee/creator",
33506
+ ],
33507
+ failed_google_candidate_link_in_bio_urls: [],
33508
+ verified_google_candidate_urls: [
33509
+ "https://www.facebook.com/creator-page",
33510
+ ],
33511
+ failed_google_candidate_urls: [],
33512
+ google_verification_partial: false,
33513
+ },
33514
+ },
33515
+ {
33516
+ name: "Get Age and Gender",
33517
+ method: "GET",
33518
+ description:
33519
+ "Get age and gender of creator. This uses AI to analyze the profile image. *The profile photo must have a clear face to get an accurate result.*",
33520
+ fullDescription:
33521
+ "Uses AI to analyze a creator's profile photo and estimate their age and gender. Returns ageRange with low and high bounds, gender, and a confidence score for the gender prediction. The profile photo must contain a clear, visible face for accurate results.",
33522
+ path: "/v1/detect-age-gender",
33523
+ sampleResponse: {
33524
+ ageRange: { low: 23, high: 29 },
33525
+ gender: "Male",
33526
+ confidence: { gender: 82.51082611083984 },
33527
+ },
33528
+ params: [
33529
+ {
33530
+ name: "url",
33531
+ type: "string",
33532
+ required: true,
33533
+ description: "URL to users social profile",
33534
+ placeholder: "https://twitter.com/levelsio",
33535
+ },
33536
+ ],
33537
+ },
32848
33538
  ],
32849
33539
  },
32850
33540
  {
@@ -32857,7 +33547,7 @@ export const apis = [
32857
33547
  method: "GET",
32858
33548
  description: "Linktree page",
32859
33549
  fullDescription:
32860
- "Scrapes a Linktree page by URL, extracting the creator's profile and all their links. Returns id, username, profilePictureUrl, description, verticals, timezone, and links — an array of link objects each with id, type, title, and url. Also includes detected social accounts (instagram, tiktok, spotify, youtube, soundcloud, apple_music) and email_address.",
33550
+ "Scrapes a Linktree page by URL, extracting the creator's profile and all their links. Returns id, username, profilePictureUrl, description, verticals, timezone, and links — an array of link objects each with id, type, title, and url. Also includes detected social accounts (instagram, tiktok, spotify, youtube, soundcloud, apple_music) and email_address. Contact fields come from the submitted public Linktree page. To request removal of your own information from Scrape Creators results, email support@scrapecreators.com with the profile URL.",
32861
33551
  path: "/v1/linktree",
32862
33552
  params: [
32863
33553
  {
@@ -33022,7 +33712,7 @@ export const apis = [
33022
33712
  method: "GET",
33023
33713
  description: "Pillar page",
33024
33714
  fullDescription:
33025
- "Scrapes a Pillar page by URL, extracting the creator's profile, social links, and products. Returns id, first_name, last_name, email, location, and social accounts (tiktok, spotify, twitter, youtube, facebook, linkedin, instagram, and more). Also includes links with click counts and products with title, price, description, and image.",
33715
+ "Scrapes a Pillar page by URL, extracting the creator's profile, social links, and products. Returns id, first_name, last_name, email, location, and social accounts (tiktok, spotify, twitter, youtube, facebook, linkedin, instagram, and more). Also includes links with click counts and products with title, price, description, and image. Contact fields come from the submitted public Pillar page. To request removal of your own information from Scrape Creators results, email support@scrapecreators.com with the profile URL.",
33026
33716
  path: "/v1/pillar",
33027
33717
  params: [
33028
33718
  {
@@ -33102,7 +33792,7 @@ export const apis = [
33102
33792
  method: "GET",
33103
33793
  description: "Linkbio (lnk.bio) page",
33104
33794
  fullDescription:
33105
- "Scrapes a Linkbio (lnk.bio) page by URL, extracting the creator's profile and all their links. Returns handle, id, social accounts (instagram, tiktok, youtube, twitter, whatsapp), email, website, and links — an array of link objects each with url and text.",
33795
+ "Scrapes a Linkbio (lnk.bio) page by URL, extracting the creator's profile and all their links. Returns handle, id, social accounts (instagram, tiktok, youtube, twitter, whatsapp), email, website, and links — an array of link objects each with url and text. Contact fields come from the submitted public Linkbio page. To request removal of your own information from Scrape Creators results, email support@scrapecreators.com with the profile URL.",
33106
33796
  path: "/v1/linkbio",
33107
33797
  params: [
33108
33798
  {
@@ -33189,7 +33879,7 @@ export const apis = [
33189
33879
  description:
33190
33880
  "Get products and other details from a creator's Amazon Shop page",
33191
33881
  fullDescription:
33192
- "Scrapes a creator's Amazon Shop page by URL, returning their storefront profile and product collections. Returns avatar, name, description, socials, and lists with title and itemCount. Also includes trendingPicks with price and discount, curations with title and postCount, and a pageToken for pagination.",
33882
+ "Scrapes a creator's Amazon Shop page by URL, returning their storefront profile and product collections. The initial request also returns videos already embedded on the storefront page without requiring a pageToken. Videos include an id, title, thumbnail, and attached ASINs. Pass each returned pageToken back unchanged with the same shop URL. A paginated page can contain lists, videos, or both. Tokens are opaque: known values can begin with amzn1.ideas, amzn1.vse.video, or amzn1.shoppablemedia, but clients should not infer the response type from the prefix.",
33193
33883
  path: "/v1/amazon/shop",
33194
33884
  params: [
33195
33885
  {
@@ -33199,6 +33889,14 @@ export const apis = [
33199
33889
  description: "URL to Amazon Shop page",
33200
33890
  placeholder: "https://www.amazon.com/shop/sydneydelrey",
33201
33891
  },
33892
+ {
33893
+ name: "pageToken",
33894
+ type: "string",
33895
+ required: false,
33896
+ description:
33897
+ "Opaque page token returned by a previous response for the same shop URL. Pass it back unchanged and do not infer the response type from its prefix. A page can contain lists, videos, or both.",
33898
+ placeholder: "amzn1.vse.video...",
33899
+ },
33202
33900
  ],
33203
33901
  sampleResponse: {
33204
33902
  success: true,
@@ -33234,6 +33932,15 @@ export const apis = [
33234
33932
  url: "https://www.amazon.com/shop/sydneydelrey/list/3PDR5YVGLMWCO",
33235
33933
  },
33236
33934
  ],
33935
+ videos: [
33936
+ {
33937
+ id: "013f01b238c94b4f9fb63f7a35783f26",
33938
+ title: "So quick and simple - keep your bike from getting stolen thi",
33939
+ thumbnail:
33940
+ "https://m.media-amazon.com/images/I/81XrHZDkc7L._AC_._SX500_SCLZZZZZZZ_.jpg",
33941
+ asins: ["B0B1ZJZRPB"],
33942
+ },
33943
+ ],
33237
33944
  trendingPicks: [
33238
33945
  {
33239
33946
  url: "https://www.amazon.com/shop/sydneydelrey/getProductDetails/B0DDJFFCB5?showRelatedPost=true",
@@ -33310,41 +34017,11 @@ export const apis = [
33310
34017
  url: "https://www.amazon.com/shop/sydneydelrey/curation/b74328f3-11ce-4a55-a844-40f6aff6e467",
33311
34018
  },
33312
34019
  ],
33313
- pageToken: "amzn1.ideas.1S28M0V6I8FUU_0_2025-09-03T01:17:37.837Z",
34020
+ pageToken: "amzn1.vse.video.0f005889de9b46f6b2499537e3ff03b0_0_2026-08-04T00:46:51.887Z",
33314
34021
  },
33315
34022
  },
33316
34023
  ],
33317
34024
  },
33318
- {
33319
- id: "age-and-gender",
33320
- name: "Age and Gender",
33321
- description: "Get age and gender of creator",
33322
- endpoints: [
33323
- {
33324
- name: "Get Age and Gender",
33325
- method: "GET",
33326
- description:
33327
- "Get age and gender of creator. This uses AI to analyze the profile image. *The profile photo must have a clear face to get an accurate result.*",
33328
- fullDescription:
33329
- "Uses AI to analyze a creator's profile photo and estimate their age and gender. Returns ageRange with low and high bounds, gender, and a confidence score for the gender prediction. The profile photo must contain a clear, visible face for accurate results.",
33330
- path: "/v1/detect-age-gender",
33331
- sampleResponse: {
33332
- ageRange: { low: 23, high: 29 },
33333
- gender: "Male",
33334
- confidence: { gender: 82.51082611083984 },
33335
- },
33336
- params: [
33337
- {
33338
- name: "url",
33339
- type: "string",
33340
- required: true,
33341
- description: "URL to users social profile",
33342
- placeholder: "https://twitter.com/levelsio",
33343
- },
33344
- ],
33345
- },
33346
- ],
33347
- },
33348
34025
  {
33349
34026
  id: "scrape-creators",
33350
34027
  name: "Scrape Creators",
@@ -33502,7 +34179,7 @@ export const apis = [
33502
34179
  method: "GET",
33503
34180
  description: "Get Linkme profile info by URL",
33504
34181
  fullDescription:
33505
- "Retrieves a Linkme profile by URL, including identity, social links, and contact details. Returns profile with id, firstName, username, bio, profileVisitCount, profileImage, verifiedAccount, and isAmbassador flag. Also includes infoLinks (email addresses) and webLinks, an array of categorized social platform links (Spotify, Instagram, YouTube, Twitter, Facebook, and more) each with linkValue and faceValue.",
34182
+ "Retrieves a Linkme profile by URL, including identity, social links, and contact details. Returns profile with id, firstName, username, bio, profileVisitCount, profileImage, verifiedAccount, and isAmbassador flag. Also includes infoLinks (email addresses) and webLinks, an array of categorized social platform links (Spotify, Instagram, YouTube, Twitter, Facebook, and more) each with linkValue and faceValue. Contact fields come from the submitted public Linkme profile. To request removal of your own information from Scrape Creators results, email support@scrapecreators.com with the profile URL.",
33506
34183
  path: "/v1/linkme",
33507
34184
  params: [
33508
34185
  {
@@ -33879,3 +34556,114 @@ export const apis = [
33879
34556
  ],
33880
34557
  },
33881
34558
  ];
34559
+
34560
+ // mirrors CACHEABLE_ROUTES in the api's responseCache.js — keep in sync.
34561
+ const CACHEABLE_PATHS = new Set([
34562
+ "/v2/instagram/media/transcript",
34563
+ "/v1/instagram/profile",
34564
+ "/v1/instagram/basic-profile",
34565
+ "/v1/instagram/post",
34566
+ "/v2/instagram/post",
34567
+ "/v3/instagram/post",
34568
+ "/v1/tiktok/profile",
34569
+ "/v2/tiktok/video",
34570
+ "/v1/facebook/adLibrary/ad",
34571
+ "/v1/facebook/adLibrary/ad/transcript",
34572
+ "/v1/facebook/post",
34573
+ "/v1/facebook/post/transcript",
34574
+ "/v1/facebook/profile",
34575
+ "/v1/youtube/channel",
34576
+ "/v1/youtube/video",
34577
+ "/v1/youtube/video/transcript",
34578
+ "/v1/google/ad",
34579
+ "/v1/find-social-profiles",
34580
+ "/v1/threads/post",
34581
+ "/v1/threads/profile",
34582
+ "/v1/twitter/profile",
34583
+ "/v1/twitter/tweet",
34584
+ "/v1/twitter/tweet/transcript",
34585
+ "/v1/pinterest/pin",
34586
+ "/v1/komi",
34587
+ "/v1/linkbio",
34588
+ "/v1/linkme",
34589
+ "/v1/linktree",
34590
+ "/v1/pillar",
34591
+ "/v1/twitch/clip",
34592
+ "/v1/twitch/profile",
34593
+ "/v1/reddit/subreddit",
34594
+ "/v1/reddit/subreddit/details",
34595
+ "/v1/reddit/ad",
34596
+ "/v1/reddit/post/transcript",
34597
+ "/v1/telegram/channel",
34598
+ "/v1/telegram/channel/posts",
34599
+ "/v1/telegram/post",
34600
+ ]);
34601
+
34602
+ const CACHE_MAX_AGE_PARAM = {
34603
+ name: "cache_max_age",
34604
+ type: "select",
34605
+ required: false,
34606
+ options: ["1d", "3d", "7d", "14d", "30d"],
34607
+ placeholder: "7d",
34608
+ };
34609
+
34610
+ // envelope fields the api adds to every response body.
34611
+ const SAMPLE_CREDITS_REMAINING = 1000000;
34612
+ const SAMPLE_CACHED_AT = "2026-07-20T14:32:11.000Z";
34613
+
34614
+ const isPlainObject = (value) =>
34615
+ value !== null && typeof value === "object" && !Array.isArray(value);
34616
+
34617
+ // prepends success/credits_remaining/credits_charged to a 200 sample.
34618
+ // values already present in the sample win; arrays are left untouched.
34619
+ const withEnvelope = (sample, creditsCharged) =>
34620
+ isPlainObject(sample)
34621
+ ? {
34622
+ success: true,
34623
+ credits_remaining: SAMPLE_CREDITS_REMAINING,
34624
+ credits_charged: creditsCharged,
34625
+ ...sample,
34626
+ }
34627
+ : sample;
34628
+
34629
+ // applied here (instead of per endpoint) so the docs, openapi spec, and
34630
+ // synced copies all pick everything up from one place.
34631
+ for (const api of apis) {
34632
+ for (const endpoint of api.endpoints) {
34633
+ const creditsCharged =
34634
+ typeof endpoint.credits === "number" ? endpoint.credits : 1;
34635
+
34636
+ endpoint.sampleResponse = withEnvelope(endpoint.sampleResponse, creditsCharged);
34637
+ for (const variant of [
34638
+ "trimmedResponse",
34639
+ "privateResponse",
34640
+ "ageRestrictedResponse",
34641
+ "gatedProfileResponse",
34642
+ ]) {
34643
+ if (endpoint[variant]) {
34644
+ endpoint[variant] = withEnvelope(endpoint[variant], creditsCharged);
34645
+ }
34646
+ }
34647
+
34648
+ if (CACHEABLE_PATHS.has(endpoint.path)) {
34649
+ const creditLabel = `${creditsCharged} ${creditsCharged === 1 ? "credit" : "credits"}`;
34650
+ endpoint.params = [
34651
+ ...(endpoint.params || []),
34652
+ {
34653
+ ...CACHE_MAX_AGE_PARAM,
34654
+ description: `If we have a response in the cache that is this many days old or newer, return the cached response (0 credits, with "cached": true and a "cached_at" timestamp). Otherwise, scrape a live result (${creditLabel}). [See the Caching page for details.](https://docs.scrapecreators.com/caching)`,
34655
+ },
34656
+ ];
34657
+ // "200 (cached)" tab: same data, free, plus cached markers at the end
34658
+ // (mirrors where the api appends them).
34659
+ if (isPlainObject(endpoint.sampleResponse)) {
34660
+ endpoint.cachedResponse = {
34661
+ ...endpoint.sampleResponse,
34662
+ credits_charged: 0,
34663
+ cached: true,
34664
+ cached_at: SAMPLE_CACHED_AT,
34665
+ };
34666
+ }
34667
+ }
34668
+ }
34669
+ }