snapchat-scraper-api
v0.0.1
Published
Snapchat scraper API client: public profile data, follower counts and Spotlight videos via ScrapingBee.
Maintainers
Readme
snapchat-scraper-api
Public Snapchat profile data for Node. One credit a profile, and a client that already knows about the two page layouts.
npm install snapchat-scraper-apiNode 16 or newer. One dependency, axios.
const { SnapchatScraper } = require('snapchat-scraper-api');
const bee = new SnapchatScraper(process.env.SCRAPINGBEE_API_KEY);Key with 1,000 free credits: scrapingbee.com.
Run against snapchat.com/add/teamsnapchat and snapchat.com/add/mrbeast on 2026-09-10.
"I want a profile record"
const p = await bee.profile('teamsnapchat');
p.display_name; // 'Team Snapchat'
p.username; // 'teamsnapchat'
p.subtitle; // 'Add me on Snapchat!'
p.snapcode; // the Snapcode SVG deeplink
p.profile_image; // the web capture preview
p.canonical; // 'https://www.snapchat.com/@teamsnapchat'bee.lastCost reads 1 after that. Snapchat delivers these pages as plain HTML, so the proxy ladder settles on its cheapest rung and no browser is opened. Adding render_js here costs five times more and returns the same thing.
The same call works on a creator profile, which is the part worth explaining.
"Why does my own scraper work on some profiles and not others"
Because Snapchat ships two layouts that disagree about headings. One rule set, two handles:
| Selector | teamsnapchat | mrbeast |
|---|---|---|
| h1 span | empty | MrBeast |
| h4 span | Team Snapchat | empty |
| h5 span | teamsnapchat | a content tile, wrong node |
| [data-testid="snapCodeImage"] | the Snapcode | empty |
They never both populate. This client asks for both headings and keeps whichever answered, so profile() returns a filled record either way. Written against h4 span alone, a scraper works on half of Snapchat and quietly writes empty strings for the rest, at HTTP 200.
Two more things it handles:
- Username from the canonical URL, not a heading. The canonical is identical on both layouts and never changes with locale, always
https://www.snapchat.com/@<handle>. - Snapcode rebuilt when the attribute is missing. That
data-testidonly exists on basic cards. Since the endpoint is keyed on username, the client constructs it, and the constructed string matched the live value exactly on both handles. No second request.
SnapchatScraper.snapcodeUrl('mrbeast'); // free, no network callAnd the rule that saves the most time: never select on a Snapchat CSS class. They look like UserDetailsCard_title__K9Awz and Heading_h400Emphasis__SQXxl. The tail after the double underscore is a build hash, so it changes on deploy and your selector starts returning nothing without any error.
"I want the follower count"
It is not in the page text. The visible DOM holds Snapchat's i18n placeholder, literally {subscriberCount} suscriptores, so a text selector hands you the template.
const s = await bee.stats('mrbeast');
s.followers; // 1463400
s.created; // '2019-05-16T14:46:37.345Z'
s.modified; // '2026-08-13T13:01:39.438Z'
s.locale; // 'en-US'
s.family_friendly; // true1 credit. The number lives in the structured data, in the counter whose interaction type is FollowAction, and this client digs it out.
created and modified are the other two you cannot get elsewhere. modified separates an active creator from a parked handle without touching a single post.
"I want their public videos"
const clips = await bee.spotlight('mrbeast');
clips.length; // 5
clips[0]; // { url, name, description, thumbnail }1 credit. An empty array is a normal answer, not a bug. teamsnapchat returned zero from the same call, because it has no public video.
"I want to check whether a handle exists"
await bee.exists('teamsnapchat'); // true
await bee.exists('dailymail'); // false
await bee.profile('dailymail'); // {}A handle with no public page answers two different ways, both observed on the same handle at different times: once as HTTP 200 with a 5,973 byte body, a bare Snapchat title and no profile object, and once as a genuine HTTP 404 forwarded from Snapchat, because 404 is one of the few statuses the API passes through untouched.
This client folds both into "no page" instead of throwing, so a batch of handles does not die on the first bad one. Test the returned value, not the status code.
"The page came back in the wrong language"
Snapchat localises on proxy exit IP. Two captures of one creator URL, identical parameters, nothing changed in between:
capture 1 MrBeast (@mrbeast) | Historias de Snapchat, Spotlight y Lentes
capture 2 og_title: MrBeast pe SnapchatSpanish, then Romanian. stats() surfaces it as locale.
What actually moves:
| Field | Locale dependent |
|---|---|
| og_title, og_description, page title, labels | yes |
| canonical, username, profile_image, snapcode | no |
| followers, created, modified | no |
So pin the country only when you read the strings:
await bee.profile('mrbeast', 'us'); // 25 credits, English
await bee.stats('mrbeast'); // 1 credit, same number either wayPinned and unpinned runs returned an identical follower value. Geotargeting needs the premium tier, so it is a twenty five times increase for a field you may not be using.
Cost
await bee.profile('teamsnapchat');
bee.lastCost; // 1
await bee.usage(); // free| Configuration | Credits | |---|---| | Auto mode, plain HTML rung | 1 | | Premium proxy with a country pinned | 25 | | Validation error | 0 |
Auto mode bills only the rung that worked and nothing when all of them fail. It cannot be combined with render_js, premium_proxy or stealth_proxy, and sending both gives HTTP 400 at no charge.
250,000 credits is 250,000 profile checks. Plan tiers.
Scope
Public profile pages. Private accounts, friend lists, Snap Map data, direct messages and story views need a signed in session, and scraping under login credentials is prohibited by ScrapingBee's terms of service.
Elsewhere
Patreon scraper API, TikTok API, TikTok search API, Twitch API, Substack scraper API, YouTube shorts API, YouTube video scraper API, YouTube metatags.
Features: data extraction, AI web scraping, screenshots, markdown scraper.
The selector durability ladder, rung by rung: github.com/ScrapingBee/snapchat-scraper-api.
License
MIT
