# Snapchat Profile Scraper & Subscriber Monitor (`neverempty/snapchat-profile-scraper`) Actor

Scrape public Snapchat profiles: subscriber count, bio, category, website and Spotlight videos with views. Turn monitoring on and a run returns a profile only when its subscriber count or Spotlight changes, for a small fee per profile checked.

- **URL**: https://apify.com/neverempty/snapchat-profile-scraper.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** Social media, Marketing, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.19 / 1,000 profile row returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Snapchat Profile Scraper & Subscriber Monitor - subscriber counts and Spotlight

Scrape public Snapchat profiles - subscriber count, display name, category, bio, website, address, profile picture and Snapcode, and the Spotlight videos on the profile with their views, shares and comments - and, with monitoring on, **receive a row only when a profile changes**: its subscriber count moved, or a new Spotlight appeared on its page. A run on which nothing changed returns a single free `no-change` row.

In monitoring mode you pay a small fee per profile checked, **$0.30 per 1,000 checks**, and the normal row price only for the rows that report a change. Watching 50 profiles every hour is 36,000 checks a month, which is **$10.80** in check fees, plus the change rows you receive.

### Best for

- **Influencer and creator vetting** - read subscriber counts, categories and Spotlight activity (latest Spotlight, Spotlight views) for a list of creators before you book them.
- **Subscriber growth tracking** - schedule monitoring and receive `subscriberDelta` only for the creators, brands or clubs whose count moved.
- **Competitor and brand monitoring** - get a row when a competitor posts a new Spotlight or its subscriber count moves.
- **Lead lists of public profiles** - website, category and address of business profiles, as Snapchat publishes them.

### What each row contains

- **What you asked for and what Snapchat returned** - `inputUsername`, `username`, `usernameMatchesInput`, `profileUrl`, `displayName`.
- **Subscribers** - `subscriberCount`, `subscriberCountShown`, `subscriberCountIsApproximate` (see below).
- **Profile** - `category`, `subcategory` (Snapchat's own labels, such as `business-group` / `sports-team`), `badgeCode` (Snapchat's raw code, not translated), `bio`, `websiteUrl`, `address`, `profilePictureUrl`, `snapcodeImageUrl`, `profileCreatedAt`, `profileLastUpdatedAt`.
- **Activity** - `spotlightsOnPage`, `latestSpotlightAt`, `moreSpotlightsOnSnapchat` (Snapchat has more than the page shows), `highlightsOnPage`, `lensesOnPage`.
- **Recent Spotlight videos** - `recentSpotlights`: `spotlightId`, `url`, `uploadedAt`, `durationSeconds`, `viewCount`, `shareCount`, `commentCount`, `thumbnailUrl`.
- **Monitoring** - `change`, `changedFields`, `isFirstCheck`, `previousCheckedAt`, `previousSubscriberCount`, `subscriberDelta`, `previousLatestSpotlightAt`.

Measured on 2026-09-14 from Apify: @fcbarcelona had `subscriberCount` 4060100 and 16 Spotlight videos on its page (the newest with 35666 views); @nasa had 759500 subscribers and 7 Spotlight videos.

#### Subscriber counts are approximate, and a hidden count is not zero

- **Snapchat publishes subscriber counts in hundreds.** Every non-zero count read on 2026-09-14 - 17 public profiles - was a multiple of 100 (4,060,100 for @fcbarcelona, 759,500 for @nasa, 13,000 for a smaller creator), and the page text rounds further ("4.1m Subscribers"). So `subscriberCountIsApproximate` is `true`, and a change smaller than that step is not visible. `subscriberDelta` is the difference between two such values.
- **Many public profiles do not show a count.** Snapchat then sends `0` - 11 of 28 public profiles read on 2026-09-14, including @cnn, whose page shows no subscriber figure at all. A real zero cannot be told apart from a hidden count, so the row says `subscriberCount: null` and `subscriberCountShown: false` instead of reporting 0 subscribers.

#### The profile is Snapchat's own, not a similar account

A profile page also contains the "similar accounts" Snapchat recommends (on @fcbarcelona: Man City, Real Madrid and FC Bayern), each with its own profile data. This Actor reads only the profile the page is about, returns the `username` Snapchat reports for it, and says in `usernameMatchesInput` whether that is the name you asked for. Spotlight videos are counted only when their creator is that username.

#### Why stories are not returned

The story part of a profile page changes from one read to the next: on 2026-09-14, reading @nfl four times about 8 seconds apart returned 14, 7, 7 and 7 story snaps, and the time of the newest snap moved forward and back again. A monitor built on that would report old snaps as new stories. So this Actor returns no story counts or times and never reports a story as a change. The Spotlight list, highlight and lens counts did not change between reads in the same measurements.

#### Phone numbers and e-mail addresses in bios

Creators often write a WhatsApp or phone number into their bio. Sequences of 8 to 15 digits (with spaces, dashes, dots or brackets) and e-mail addresses in `bio` are replaced with `[phone removed]` and `[email removed]`. Shorter numbers, such as licence numbers, and year ranges are kept.

### Monitoring, and what it costs

Turn **monitoring mode** on and the Actor remembers each profile. On later runs a profile comes back only with one of these `change` values:

| `change` | Meaning |
|---|---|
| `first-check` | The profile had not been seen before. Every profile is returned once on the first run, to set the baseline. |
| `changed` | `changedFields` says what: `subscriberCount` (the displayed count moved, or the profile started or stopped showing it), `spotlight` (a Spotlight newer than the one remembered). |

With `monitorMode` set to `subscriber-change`, only `subscriberCount` changes are returned; new Spotlights are remembered but not returned.

A profile that did not change is **not returned**, so it costs no row price; the check fee for reading it still applies. Profiles are remembered **per username, not per list**, so adding a profile does not reset the ones already being watched. In monitoring mode `maxProfiles` does not cut changes: every changed profile among those read is returned. If the run's maximum total charge stops a change from being delivered, that change is not remembered, so the profile still counts as changed the next time it is checked.

Names that do not exist and accounts without a public profile are not remembered. If `usernames` is empty in monitoring mode, nothing is checked or charged: the run returns one free `invalid-input` row.

**Do not put the same profile in two schedules that can run at the same time.** Each run writes back only the profiles it checked, merged into the records as they are at that moment, then reads them again and writes once more if another run overwrote them - so two overlapping runs over different profiles keep each other's history. But Apify's key-value store has no atomic update, so this cannot be made watertight: runs that finish at the same instant, or check the same profile at the same time, can still overwrite each other's record, and the next run may return a `first-check` or a change a second time.

#### What monitoring costs

- **$0.30 per 1,000 profile checks** - charged in monitoring mode for every public profile that was read, whether or not it changed. Names that do not exist, accounts without a public profile and bot checks are not charged.
- **The row price** - charged only for the rows returned, which in monitoring mode means `first-check` rows and changes.

The Actor reads only as many profiles as the run's maximum total charge can pay for with both a check and a change row each, so a low limit cannot use up the budget on check fees and leave nothing for the rows. Profiles beyond that are not checked; a `budget-reached` row says how many, and raising the maximum total charge lets them be checked. Runs with monitoring off are charged per row only.

### Rows that are never charged

When there is nothing to return, this Actor says why instead of returning an empty result:

- `no-such-account` - Snapchat answered HTTP 404: there is no account with that name.
- `no-public-profile` - the account exists but has no public profile (for example @espn on 2026-09-14), so Snapchat shows no subscriber count, bio or Spotlight. The display name is not returned, because on a personal account it can be a private person's name.
- `blocked` - Snapchat answered with a bot check or an empty response. Profiles are requested directly first, and only this answer makes the run switch to a proxy session and try again.
- `unreadable` - the page could not be read, or it did not have the shape this Actor knows. Nothing is guessed.
- `no-change` - monitoring ran and no profile changed.
- `invalid-input` - the text is not a Snapchat username or profile URL, or monitoring mode is on with no username, so nothing was requested.
- `example-input` - `usernames` was empty with monitoring off, so the example profiles were read; this row says so, and the example profile rows themselves are normal charged rows.
- `budget-reached` - the run's maximum charge was reached: the row says how many ready rows fit, or how many profiles were not checked in monitoring mode.
- `not-checked` - the end of your list was not checked, because `maxProfiles` profiles had already been read (monitoring off), or because more than 1,000 usernames were given. The row says how many.

### Input

| Field | What it does |
|---|---|
| `usernames` | The profiles to read: `@name`, `name`, `https://www.snapchat.com/@name` or `https://www.snapchat.com/add/name`. Names are sent in lower case, so `@FCBarcelona` and `@fcbarcelona` are the same profile and are read once. If empty with monitoring off, the example profiles @fcbarcelona and @nasa are read and charged as normal rows, with a free `example-input` row saying so; if empty in monitoring mode, nothing is read or charged. |
| `maxProfiles` | How many charged profile rows to return (up to 1,000). |
| `includeRecentSpotlights` | Return the Spotlight videos on the profile page with their views, shares and comments (on by default). |
| `monitoringMode` | Remember each profile and return it only when it changes. |
| `monitorMode` | `any-change` (subscribers or Spotlight) or `subscriber-change` (subscribers only). |
| `resetMonitoringState` | Forget every remembered profile and start a fresh baseline. |
| `useProxy` | Retry through a proxy if Snapchat answers with a bot check. Every profile is requested directly first. |

### Questions

**Can I get the exact subscriber count?**
No. Snapchat publishes the count in hundreds on the public profile, and that is the number returned. Many profiles do not show a count at all; those rows say `subscriberCountShown: false`.

**Does it work for private or personal accounts?**
Only public profiles (creators, public figures, brands and businesses) have a subscriber count, bio and Spotlight on the web. A personal account comes back as a free `no-public-profile` row.

**Does monitoring charge me when nothing changed?**
Unchanged profiles are not returned and cost no row price. Each public profile checked costs the check fee ($0.30 per 1,000), changed or not - that is what pays for polling.

**Does it download Spotlight videos?**
No. It returns counts, times, statistics and the Spotlight page URLs; it does not download or store any media.

**Is the Spotlight list complete?**
It is what Snapchat puts on the profile page. When Snapchat has more, `moreSpotlightsOnSnapchat` is `true` and `spotlightsOnPage` is the number on the page, not the total.

### Example input

```json
{
  "usernames": ["@fcbarcelona", "@nasa", "https://www.snapchat.com/add/nfl"],
  "monitoringMode": true,
  "monitorMode": "any-change",
  "includeRecentSpotlights": true,
  "maxProfiles": 100
}
```

# Actor input Schema

## `usernames` (type: `array`):

Public profiles to read: @name, name, https://www.snapchat.com/@name or https://www.snapchat.com/add/name (with or without the scheme, share links with ?share\_id= work). Names are sent in lower case, as Snapchat redirects capitals to the lower-case name, and duplicates are read once. Up to 1,000 per run. If you leave this empty with monitoring off, the example profiles @fcbarcelona and @nasa are read and charged as normal rows, and a free example-input row says so; in monitoring mode an empty list checks and charges nothing.

## `maxProfiles` (type: `integer`):

How many charged profile rows to return when monitoring is off: reading stops once this many public profiles have been read, and a free row says how many entries at the end of the list were not checked. Names that do not exist and accounts without a public profile do not count. In monitoring mode it does not limit the changes returned - every changed profile among those read comes back.

## `includeRecentSpotlights` (type: `boolean`):

Return the Spotlight videos Snapchat puts on the profile page (the most recent ones, not the full history) with upload time, duration, view, share and comment counts and the Spotlight URL. The counts spotlightsOnPage and latestSpotlightAt are returned either way.

## `monitoringMode` (type: `boolean`):

Off = every profile you listed comes back, charged per row. On = the Actor remembers each profile and, on later runs, returns it only when something changed, with the previous value (subscriberDelta, previousSubscriberCount, previousLatestSpotlightAt). The first run returns every profile once to set the baseline. **In monitoring mode every public profile checked costs $0.30 per 1,000 checks, changed or not** (names that do not exist, accounts without a public profile and bot checks are free), plus the row price for the rows returned. Example: 50 profiles checked every hour = 36,000 checks a month = $10.80. The Actor reads only as many profiles as the run's maximum total charge can pay for with a check and a change row each. Profiles are remembered per username; do not put the same profile in two schedules that can run at the same time.

## `monitorMode` (type: `string`):

Any change = the displayed subscriber count moved (including a profile starting or stopping to show it), or a newer Spotlight appeared on the profile page. Stories are not watched, because the story part of the page changes from one read to the next. Subscriber change only = only the displayed subscriber count. Snapchat shows subscriber counts in hundreds, so a change smaller than that is not visible.

## `resetMonitoringState` (type: `boolean`):

Clears every remembered profile for this Actor in your account, so the next monitoring run returns each profile once again. This affects all your monitoring runs, because profiles are stored per username rather than per list.

## `useProxy` (type: `boolean`):

Every profile is requested directly first, which worked from Apify on every attempt measured on 2026-09-14. If Snapchat answers with a bot check or an empty response, this switches to a proxy session and tries again. With it off, that answer is returned as a free 'blocked' row and no proxy is paid for.

## Actor input object example

```json
{
  "usernames": [
    "@fcbarcelona",
    "@nasa"
  ],
  "maxProfiles": 100,
  "includeRecentSpotlights": true,
  "monitoringMode": false,
  "monitorMode": "any-change",
  "resetMonitoringState": false,
  "useProxy": true
}
```

# Actor output Schema

## `results` (type: `string`):

One row per public Snapchat profile: the username you asked for and the one Snapchat returned, display name, subscriber count (shown in hundreds, or null when the profile does not show it), category, bio, website, address, profile picture and Snapcode, when the profile was created and last updated, how many Spotlight videos, highlights and lenses its page shows, the recent Spotlight videos with views, shares and comments, and, in monitoring mode, what changed since the last run with the previous values. Names that do not exist, accounts without a public profile and bot checks come back as their own free rows; in monitoring mode unchanged profiles are not returned.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "usernames": [
        "@fcbarcelona",
        "@nasa"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/snapchat-profile-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "usernames": [
        "@fcbarcelona",
        "@nasa",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("neverempty/snapchat-profile-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "usernames": [
    "@fcbarcelona",
    "@nasa"
  ]
}' |
apify call neverempty/snapchat-profile-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,neverempty/snapchat-profile-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/eTYZRUvF1OIF33f2A/builds/w9gbkMv1UE6xWD9zV/openapi.json
