# TikTok Story Monitor - New Story Alerts for Any Account (`seemuapps/tiktok-story-monitor`) Actor

Monitor TikTok accounts for new stories on a schedule. Get only stories posted since the last run, with no-watermark video, cover, caption and views.

- **URL**: https://apify.com/seemuapps/tiktok-story-monitor.md
- **Developed by:** [Seemu Scraping](https://apify.com/seemuapps) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 new stories

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## TikTok Story Monitor - New Story Alerts for Any Account

Watch a list of TikTok accounts and get alerted the moment they post a new story. Put the actor on a schedule and every run returns **only the stories posted since the previous run**: the no-watermark video or photos, cover image, caption, posting and expiry time, and views. No login, no TikTok account, and the creator never sees you in their viewer list.

TikTok stories disappear after 24 hours. Run this monitor every hour (or every few hours) and you'll never miss one, without getting the same story twice.

### What you get

One row per **new** story with:

- **Story**: `storyId`, `type` (`video` or `image`), `createdAt`, `expiresAt`, `hoursLeft`, `caption` and on-screen sticker text
- **Media**: `playUrl` (no-watermark video), `cover`, `imageUrls` for photo stories, duration, width and height
- **Saved files** (optional): with **Save story files** on, each new video or photo is saved to your Apify storage and `mediaFileUrl` / `downloadedFiles` hold permanent links that keep working after the story expires
- **Engagement**: views, likes, comments, shares and saves, when TikTok shows them
- **Monitoring fields**: `isNew`, `firstSeenAt` (when this monitor first saw the story), `monitorId` and `checkedAt`
- **Account**: username, display name, user ID and profile link

Every run also saves a **SUMMARY** record in the **Key-value store** tab: accounts checked, new stories, saved files, errors, and a per-account breakdown (`ok`, `private`, `not_found`, `error`, `not_processed`).

### Use cases

- **Competitor and brand monitoring**: get notified whenever a rival brand posts a TikTok story
- **Influencer marketing**: confirm sponsored creators posted the agreed story, with proof and view counts, without checking manually
- **Story archiving**: save every story before it disappears after 24 hours
- **Fan and creator alerts**: push new stories from favourite creators to Slack, Discord, email or a Google Sheet
- **Social media reporting**: build a running log of story activity for a roster of accounts

### How to use

1. Enter the TikTok usernames (with or without @) or profile URLs to watch, one per line
2. Give the watch list a **Monitor name** (for example `competitors`). Runs with the same name share one memory of stories already returned
3. Optionally turn on **Save story files** to keep permanent copies of the videos and photos
4. Run the actor once. The first run returns every story that is live right now
5. Set up a schedule (below). From now on each run returns only new stories, and an empty dataset means nothing new was posted

#### How the monitor remembers stories

The monitor keeps the IDs of stories it has already returned in a named key-value store in your own Apify account, called `tiktok-story-monitor-<monitor name>` (for example `tiktok-story-monitor-competitors`). It survives between runs and schedules, and story IDs are forgotten after 48 hours because stories expire after 24.

- Use a **different monitor name for each schedule or task** so separate watch lists don't hide each other's stories
- To start fresh, delete that key-value store in **Storage** → **Key-value stores**, or pick a new monitor name
- Avoid running two runs with the same monitor name at the same time

#### Step 1: Schedule it

1. Save your input as a task: **Actions** → **Save as a new task**
2. Go to **Schedules** → **Create new**
3. Pick a frequency. Every hour (`0 * * * *`) catches stories within the hour. Every 6 hours (`0 */6 * * *`) is enough to never miss one, since stories last 24 hours
4. Add your task to the schedule and save

#### Step 2: Get alerts

Open your task → **Integrations** and choose how you want to hear about new stories:

- **Slack, email, Google Sheets, Zapier or Make**: pick the integration, trigger it on **Run succeeded**, and it receives the run's dataset of new stories
- **Webhook** (your own server, n8n, Discord bot, etc.): **Add integration** → **HTTP webhook**, event type **Run succeeded**, and your URL. Your endpoint receives the run details, including `resource.defaultDatasetId`. Fetch the new stories from `https://api.apify.com/v2/datasets/<defaultDatasetId>/items`, or read the counts from `https://api.apify.com/v2/key-value-stores/<defaultKeyValueStoreId>/records/SUMMARY`

To alert only when there is something new, check `newStories > 0` in the SUMMARY record (or that the dataset has items) before sending the notification. The run's status message also says how many new stories were found.

### Output example

```json
{
  "monitorId": "competitors",
  "username": "jamescharles",
  "nickname": "James Charles",
  "userId": "190068318278651904",
  "storyId": "7697745590247017742",
  "isNew": true,
  "firstSeenAt": "2026-10-18T20:27:19.124Z",
  "createdAt": "2026-10-17T21:04:35.000Z",
  "expiresAt": "2026-10-18T21:04:35.000Z",
  "hoursLeft": 0.6,
  "type": "video",
  "caption": null,
  "stickerText": [],
  "durationSeconds": 25,
  "width": 720,
  "height": 1280,
  "playUrl": "https://v16-webapp-prime.tiktok.com/video/tos/...",
  "cover": "https://p19-common-sign.tiktokcdn.com/...",
  "imageUrls": [],
  "views": 65800,
  "likes": 1331,
  "comments": 0,
  "shares": 20,
  "saves": 0,
  "musicTitle": "original sound",
  "musicAuthor": "Painted",
  "mediaFileUrl": "https://api.apify.com/v2/key-value-stores/.../records/jamescharles-7697745590247017742",
  "downloadedFiles": [
    {
      "url": "https://api.apify.com/v2/key-value-stores/.../records/jamescharles-7697745590247017742",
      "fileName": "jamescharles-7697745590247017742.mp4",
      "contentType": "video/mp4",
      "sizeBytes": 1755048
    }
  ],
  "profileUrl": "https://www.tiktok.com/@jamescharles",
  "checkedAt": "2026-10-18T20:27:19.124Z"
}
```

A photo story has `type: "image"`, its pictures in `imageUrls`, and one saved file per photo.

### Pricing

Pay-per-event, so you only pay for what each run actually does:

| Event | When it's charged |
|---|---|
| Run | Once per run |
| Account check | Each account checked successfully, with or without new stories |
| New story | Each story returned for the first time. Stories you've already received are never charged again |
| Saved file | Each video or photo saved when **Save story files** is on |
| Account lookup | Rarely: when an account's ID can't be confirmed for free, at most once a week per account |

Private accounts, invalid input and failed checks are free (failed accounts are retried on the next run). Usernames that don't exist are free unless they needed an account lookup to confirm. Even then, the result is remembered for 24 hours so you aren't charged again. A schedule that checks 10 accounts every hour mostly costs the run and account-check fees, plus new stories when they appear.

Free Apify plans can watch up to 10 accounts per run (3 runs a day). Upgrade to a paid plan to remove these limits and schedule as often as you like.

### FAQ

**Why is my dataset empty?** None of the accounts posted a new story since the previous run with this monitor name. That's the expected result for a monitor. Check the SUMMARY record to see every account that was checked.

**Why did the first run return so many stories?** The first run with a new monitor name has no memory yet, so every live story counts as new. Later runs return only what's new.

**I want to see the same stories again.** Turn on **Also return already-seen stories** (they come back free with `isNew: false`), use a new monitor name, or delete the monitor's key-value store.

**Will the creator know I viewed their story?** No. Stories are fetched anonymously, without a TikTok account, so you never appear in the viewer list.

**Can I monitor private accounts?** No. Only public stories are available.

**How long do the links work?** `playUrl`, `cover` and `imageUrls` are TikTok's temporary links and stop working after a few hours. Turn on **Save story files** for permanent links in your Apify storage. Very large video files (over 13 MB) are not saved, but their `playUrl` is still returned.

**Does the video have a watermark?** No. `playUrl` and the saved file are the no-watermark version.

# Actor input Schema

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

Accounts to watch: usernames (with or without @) or profile URLs, one per line (up to 1,000 per run).

## `monitorId` (type: `string`):

Name of this watch list's memory of already-returned stories. Runs with the same name share it, so keep it fixed on a schedule. Use a different name per schedule or task (letters, numbers and hyphens). Leave empty for 'default'.

## `downloadMedia` (type: `boolean`):

Save each new story's video or photos to the run's key-value store and add permanent download links. Turn off to get TikTok's media links only (they expire after a few hours).

## `includeSeenStories` (type: `boolean`):

Also list stories that are still live but were returned by an earlier run (isNew = false, free, files not saved again). Leave off to get only new stories, which is best for alerts.

## Actor input object example

```json
{
  "usernames": [
    "jamescharles",
    "noahbeck"
  ],
  "monitorId": "default",
  "downloadMedia": false,
  "includeSeenStories": false
}
```

# Actor output Schema

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

One row per story first seen in this run: username, story ID, posted and expiry times, type (video/image), no-watermark video link, cover, caption, views, likes, comments, shares, saves, isNew, firstSeenAt and saved file links.

## `summary` (type: `string`):

SUMMARY record: accounts checked, new stories, saved files, errors, and a per-account breakdown with status.

## `files` (type: `string`):

Story videos and photos saved to the default key-value store (when Save story files is on).

# 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": [
        "jamescharles",
        "noahbeck"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("seemuapps/tiktok-story-monitor").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": [
        "jamescharles",
        "noahbeck",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("seemuapps/tiktok-story-monitor").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": [
    "jamescharles",
    "noahbeck"
  ]
}' |
apify call seemuapps/tiktok-story-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,seemuapps/tiktok-story-monitor"
        }
    }
}
```

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/AqOSahX0NG4dY6Akv/builds/73JrPREhOjqmu3OUT/openapi.json
