snapchat-scraper-api
A Python client for public Snapchat profile data through ScrapingBee. Built around the fact that most selectors on a Snapchat profile are guaranteed to break, and the ones that are not live somewhere unobvious.
Verified against snapchat.com/add/teamsnapchat and snapchat.com/add/mrbeast on 2026-09-10. Three findings below only surface on a live run: there are two incompatible page layouts, the follower count is not in the visible text at all, and the page language depends on which country the request left from.
pip install snapchat-scraper-api
Requires Python 3.8 or newer and requests.
The cheapest target in the series
One credit per profile. Snapchat serves these pages as delivered HTML, so mode=auto settles on the plain rung and never opens a browser. Do not add render_js out of habit, it buys nothing here and costs five times more.
What is in scope
Public profile pages, read anonymously: display name, username, subtitle, Snapcode, preview image, canonical URL, follower count, profile creation and last modified dates, Snapchat's family friendly flag, and public Spotlight or highlight videos.
Out of scope: private accounts, friend lists, Snap Map location data, direct messages and story view data. Those need a signed in session, and scraping under login credentials is prohibited by ScrapingBee's terms of service.
Authentication
from snapchat_scraper_api import SnapchatScraper
bee = SnapchatScraper("YOUR_API_KEY")
Sent as Authorization: Bearer YOUR_API_KEY. Key and 1,000 free credits: ScrapingBee. Landing page: Snapchat scraper API.
Method reference
profile(username, country=None)
1 credit unpinned, 25 credits with a country pinned.
bee.profile("teamsnapchat")
{'display_name': 'Team Snapchat',
'username': 'teamsnapchat',
'subtitle': 'Add me on Snapchat!',
'snapcode': 'https://app.snapchat.com/web/deeplink/snapcode?username=teamsnapchat&type=SVG&bitmoji=enable',
'profile_image': 'https://www.snapchat.com/web-capture/www.snapchat.com/@teamsnapchat/preview/square.jpeg?xp_id=1',
'og_title': 'Team Snapchat on Snapchat',
'og_description': 'Team Snapchat is on Snapchat!',
'canonical': 'https://www.snapchat.com/@teamsnapchat'}
The same call works on a creator profile, which matters more than it sounds.
Snapchat serves two incompatible layouts. Both handles below were fetched with one rule set:
| Selector | teamsnapchat (basic card) |
mrbeast (creator profile) |
|---|---|---|
h1 span |
empty | MrBeast |
h4 span |
Team Snapchat |
empty |
h5 span |
teamsnapchat |
wrong node, the page has ten h5 elements |
[data-testid="snapCodeImage"] |
the Snapcode URL | empty |
They are mutually exclusive. This client requests both headings and returns whichever is populated, so one call covers both page types. A scraper written against only h4 span works on half of Snapchat and returns empty strings on the other half, with a 200 status and no error.
Three more decisions the client makes for you:
- The username comes from the canonical URL, not from a heading. The canonical is byte identical across layouts and does not change with locale, and it always reads
https://www.snapchat.com/@<username>. - The Snapcode is rebuilt when the selector is empty. The endpoint is parameterised by username, and the constructed string matches the live selector value exactly, verified on both handles. No second request.
- An empty dict means the handle has no public page. More on that below.
Never select on CSS module classes. Snapchat ships class names like UserDetailsCard_title__K9Awz, Heading_h400Emphasis__SQXxl and DesktopUserProfile_desktopContainer__UwOc_. The suffix after the double underscore is a build hash. It rotates on deploy, and a scraper keyed on it silently returns empty strings afterwards.
stats(username, country=None)
1 credit. Follower count and account dates, from the application/ld+json block.
bee.stats("mrbeast")
# {'name': 'MrBeast',
# 'username': 'mrbeast',
# 'url': 'https://www.snapchat.com/@mrbeast',
# 'image': 'https://cf-st.sc-cdn.net/aps/bolt/...',
# 'followers': 1463400,
# 'created': '2019-05-16T14:46:37.345Z',
# 'modified': '2026-08-13T13:01:39.438Z',
# 'locale': 'en-US',
# 'family_friendly': True}
The follower count is not in the visible text. The DOM carries the i18n template placeholder, literally {subscriberCount} suscriptores, so a text selector returns the template rather than a number. The real value sits in interactionStatistic, in the counter whose interactionType is FollowAction. This client digs it out.
created and modified are the other two fields available nowhere else. modified is how you separate an active creator from a dormant handle without fetching a single post.
Returns None when there is no public profile page.
Note this parses the fetched HTML rather than using extract_rules, because extract_rules cannot read script tag contents. A rule selecting script[type="application/ld+json"] returns None, tested directly.
spotlight(username, country=None)
1 credit. Public Spotlight and highlight videos, from the ItemList block.
bee.spotlight("mrbeast")
# [{'url': 'https://www.snapchat.com/@mrbeast/highlight/91542d31-...',
# 'name': 'A Snapchat video by MrBeast',
# 'description': 'A Snapchat video by MrBeast',
# 'thumbnail': 'https://cf-st.sc-cdn.net/d/...'}, ...]
Five entries on the creator page tested. An empty list is normal, not a failure. The same block came back as an empty array on teamsnapchat.
exists(username)
1 credit. Whether the handle has a public profile page.
bee.exists("teamsnapchat") # True
bee.exists("dailymail") # False
A missing handle answers in two different ways, and both were observed on the same handle at different times. One capture returned HTTP 200 with a 5,973 byte body, a bare Snapchat title and no ProfilePage block. A later capture returned a real HTTP 404, forwarded straight through because 404 is one of the few statuses ScrapingBee does not rewrite.
This client treats both as "no page" rather than raising, so a batch run does not die on one bad handle. Decide on the presence of the ProfilePage block, not on the status code.
snapcode_url(username, svg=True, bitmoji=True)
A static method. 0 credits, no request.
SnapchatScraper.snapcode_url("teamsnapchat")
# 'https://app.snapchat.com/web/deeplink/snapcode?username=teamsnapchat&type=SVG&bitmoji=enable'
usage()
Free. Account credits, concurrency and renewal date.
The locale trap
Snapchat localises by proxy exit IP, and without a country parameter whichever region the request left from decides the language of every title, subtitle and label you parse.
Two captures of the same creator URL, same parameters, no change in between:
capture 1 title: MrBeast (@mrbeast) | Historias de Snapchat, Spotlight y Lentes
capture 2 og_title: MrBeast pe Snapchat og_description: MrBeast este pe Snapchat!
Spanish, then Romanian. The structured data tells you it happened, through inLanguage, which stats() returns as locale.
What moves and what does not:
| Field | Locale dependent |
|---|---|
og_title, og_description, page title, visible labels |
yes |
canonical, username, profile_image, snapcode |
no |
followers, created, modified |
no |
So pin the country only when you actually read the strings:
bee.profile("mrbeast", country="us") # 25 credits, English guaranteed
bee.stats("mrbeast") # 1 credit, the number is the same either way
Pinning gave an identical followers value on both runs. Geotargeting requires the premium tier, which is a twenty five times cost increase, so do not turn it on for numeric work.
Credit cost
Measured from spb-cost headers. Available on bee.last_cost.
| Configuration | Credits |
|---|---|
mode=auto, settled on plain HTML |
1 |
premium_proxy with country_code |
25 |
| Validation error | 0 |
mode=auto bills only the rung that worked and nothing if every rung fails. It is incompatible with render_js, premium_proxy and stealth_proxy, and sending both returns HTTP 400 while billing nothing.
At 1 credit per profile, 250,000 credits covers 250,000 profile checks. Plan tiers: ScrapingBee pricing.
Related
Adjacent social and creator landing pages: Patreon scraper API, TikTok API, TikTok search API, TikTok follower API, Twitch API, Substack scraper API, YouTube shorts API, YouTube video scraper API, YouTube title scraper API.
Features: data extraction, AI web scraping, screenshots, markdown scraper, JavaScript scenario, n8n integration.
Reference: extraction rules documentation. The selector durability walkthrough is at github.com/ScrapingBee/snapchat-scraper-api.
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file snapchat_scraper_api-0.0.1.tar.gz.
File metadata
- Download URL: snapchat_scraper_api-0.0.1.tar.gz
- Upload date:
- Size: 13.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
57c24052e48902d0af0a54c34dd0c2336305905e2c627c1488c981c210db7d28
|
|
| MD5 |
16a625c68edddd4abd7c5da3f9d48b37
|
|
| BLAKE2b-256 |
28b69272a5a9136b72b18805f3aa4a8b3f7c9ad3c942b5770733583da468d27d
|
File details
Details for the file snapchat_scraper_api-0.0.1-py3-none-any.whl.
File metadata
- Download URL: snapchat_scraper_api-0.0.1-py3-none-any.whl
- Upload date:
- Size: 10.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5d664c76cd55cd742607329295b0bcb5a4090ee64d6822eb89f4d8e8ecf728dd
|
|
| MD5 |
67f21516417de692e848a6b38ff88a44
|
|
| BLAKE2b-256 |
55df02865cc80c50b14f3769eb3d5c1366cd96f384a6a82b389265e688d5d6c3
|