TikTok Ads Library Dataset Monitor & Alerts
Pricing
from $10.00 / 1,000 completed monitor checks
TikTok Ads Library Dataset Monitor & Alerts
Monitor TikTok Ads Library exports for competitor changes. Detect new ads and verified changes to creatives, copy, CTAs, landing pages, targeting, reach and status. Use authorized Apify Datasets or JSON—no TikTok API key, browser, proxy or extractor lock-in; ready for schedules and webhooks.
Pricing
from $10.00 / 1,000 completed monitor checks
Rating
0.0
(0)
Developer
Vadim Bezrukov
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
This Actor turns authorized ad exports into conservative, webhook-ready competitor alerts. It remembers the last successful state for every monitor and distinguishes a new observation from a verified change.
This Actor does not scrape or contact TikTok. Supply ad snapshots inline or by Apify Dataset ID. That keeps the monitoring contract stable when an upstream provider changes and lets you use a source you are authorized to use.
To try it, keep the prefilled one-ad sample and click Start. The run makes no
external request, writes a BASELINE event plus a monitor-health row, and costs
$0.0101.
Use from AI agents with MCP
Connect the public Actor directly at
https://mcp.apify.com?tools=automa-flow/tiktok-ads-dataset-monitor. Ask your
agent to compare an authorized complete ad snapshot with the previous successful
state and act only on the Actor's verified change status.
How TikTok competitor ad monitoring works
- Run any TikTok Ads Library source you are authorized to use.
- Pass its complete Dataset—or your own JSON snapshot—to this Actor.
- The first successful run creates a baseline. Later complete runs emit only candidate or confirmed changes by default.
- Send confirmed event rows to Slack, email, Make, n8n, a sheet, or your own webhook workflow.
The result is a source-independent changefeed. You can replace an upstream extractor without replacing the alerting and state contract.
What you get
BASELINEon the first successful run, never a flood of fake new ads;NEW_AD, creative, copy, CTA, landing-page, targeting, reach and status events;CANDIDATEversusCONFIRMEDverification;- optional corroboration from two independent snapshots for one monitor;
- one explicit status row per monitor, including valid
NOT_FOUND,PARTIALandFAILEDoutcomes; - last-good KVS state that is not overwritten by failed or incomplete feeds;
- stable IDs, normalized URLs, semantic fingerprints and
previousvalues.
An ad disappearing from a result list never becomes AD_BECAME_INACTIVE.
Inactivity requires an observed active: false value from a feed whose
authoritativeStatus you explicitly enabled.
Who it is for
- agencies receiving daily client/competitor ad exports;
- performance marketing and creative-strategy teams;
- users chaining an existing TikTok Ads Actor into a reliable monitor;
- data pipelines that need an auditable changefeed rather than periodic dumps.
If you need this Actor to fetch TikTok itself, it is the wrong product. TikTok's official API requires approved access, while the public library currently restricts unapproved automated extraction. This Actor deliberately stays on the processing side of that boundary.
Quick start with an inline snapshot
{"feeds": [{"monitorId": "nike-de","externalId": "nike","sourceName": "my-authorized-export","isComplete": true,"priority": 10,"observations": [{"adId": "123456789","adDetailsUrl": "https://library.tiktok.com/ads/detail/?ad_id=123456789","advertiserName": "Nike","title": "Example creative","description": "Example copy","callToAction": "SHOP_NOW","status": "active","destinationUrl": "https://example.com/product?utm_source=tiktok","videoUrl": "https://cdn.example/video/creative.mp4?expires=123","country": "DE"}]}],"mode": "monitor","outputMode": "changesOnly","verificationMode": "safe","stateNamespace": "agency-client-a"}
The first successful run emits BASELINE. If the next complete run contains a
new ad, safe mode emits it as NEW_AD / CANDIDATE. The following consecutive
complete run confirms it. Two independent feeds containing the same new ad ID
confirm it immediately.
Monitor an Apify Dataset
Select the upstream run's Dataset and give that inventory a stable monitor ID:
{"datasetIds": ["UPSTREAM_DEFAULT_DATASET_ID"],"datasetMonitorId": "nike-de","datasetExternalId": "nike","datasetSourceNames": ["primary-export"],"datasetIsComplete": true,"mode": "monitor","outputMode": "changesOnly","verificationMode": "safe","stateNamespace": "agency-client-a"}
A practical recurring workflow is:
upstream Task succeeds-> webhook starts this Actor with resource.defaultDatasetId in datasetIds-> confirmed event rows trigger Slack, email, Make, n8n or another webhook
Keep one logical advertiser/query inventory in each Dataset workflow. If an upstream Dataset contains several advertisers, split or transform it before this Actor; otherwise those ads would intentionally be treated as one inventory. The native Dataset picker grants this Actor read-only access only to the Datasets you select. Candidate rows can trigger an n8n/Make verification branch that runs a second source and calls this Actor again with both snapshots, so expensive corroboration stays on demand.
Do not schedule this Actor repeatedly against one immutable Dataset ID—that only
rechecks the same snapshot. Schedule the upstream Task, then start this Actor
from the upstream run's Succeeded integration so every check receives the
new defaultDatasetId.
Dataset IDs must be supplied through the top-level datasetIds field. A legacy
nested feeds[].datasetId cannot receive read permission under the Actor's
limited-permissions policy, so that feed is returned as invalid with a migration
hint while other inline feeds continue.
Dataset views intentionally show all rows because Apify view transformations do
not filter records. In exports and integrations, select confirmed events with
record_type = ad_event and verification_status = CONFIRMED, candidates with
verification_status = CANDIDATE, and health rows with
record_type = monitor_status.
Only mark datasetIsComplete: true when every selected Dataset completed its
required pagination. For inline failures, send status: "FAILED" without
observations. A valid complete zero-ad Dataset is NOT_FOUND; it is not
FAILED and does not erase known ads.
Independent source verification
Select several Datasets for the same inventory and give them distinct source names in the same order:
{"datasetIds": ["DATASET_A", "DATASET_B"],"datasetMonitorId": "nike-de","datasetSourceNames": ["primary-export", "verification-export"],"datasetIsComplete": true,"verificationMode": "safe"}
The first Dataset supplies the canonical observation. Other sources provide
evidence. Inline feeds can override this ordering with priority. A new ad ID
seen by two distinct sources is confirmed even if one
source exposes fewer optional fields. A semantic change requires identical new
normalized content from two sources or the same primary source on two
consecutive complete runs.
Verification modes
| Mode | New or changed data | Disappearance |
|---|---|---|
safe (default) | confirmed by two sources or two consecutive complete runs | never treated as inactive |
fast | one complete feed confirms immediately | never treated as inactive |
safe is recommended for alerts. fast is useful when the upstream already
provides contractual completeness and correctness guarantees.
Compatible fields
The automatic normalizer recognizes common camelCase and snake_case fields, including:
adId,ad_id,source_id, or an ID inadDetailsUrl;advertiserName,advertiser_name, oradvertiser.name;description,creativeText,text,ad_text;callToAction,cta,call_to_action;destinationUrl,landingUrl,landing_url;videoUrl(s),imageUrl(s),coverImageUrl;firstShownDate,lastShownDate,active,status;countries,targeting,estimatedAudience,impressions.
A stable ad ID is mandatory. Rows without one make the feed PARTIAL; valid
rows are reported in its diagnostics but cannot advance monitoring state.
Signed media query parameters and common tracking parameters (utm_*,
ttclid, gclid) do not affect fingerprints.
Output contract
Every Dataset contains:
- one
monitor_statusrow per logicalmonitorId; - zero or more
ad_eventrows.
Important fields:
record_type, source, source_id, source_url, scraped_at,schema_version, fingerprint, external_id, monitor_id,status, change_type, changed_fields, verification_status,ad_id, advertiser_name, text, cta, active, landing_url,media_ids, countries, targeting, reach, impressions,source_metadata, previous, error
Example confirmed change row:
{"record_type": "ad_event","monitor_id": "nike-de","source_id": "tiktok-ad:123456789","status": "SUCCESS","change_type": "CTA_CHANGED","changed_fields": ["cta"],"verification_status": "CONFIRMED","ad_id": "123456789","advertiser_name": "Nike","cta": "SHOP_NOW","previous": {"cta": "LEARN_MORE"},"source_metadata": {"verificationReason": "same_source_consecutive_confirmation","candidateRuns": 2}}
source_metadata explains the decision: primary source, all sources that saw
the ad, exact semantic matches, disagreements, candidate run count and the
verification reason. Output is append-only and suitable as a webhook payload.
Automate schedules and webhooks
In the upstream Actor or Task, open Integrations, choose this Actor, set Start when to Run succeeded, and paste this input:
{"datasetIds": ["{{resource.defaultDatasetId}}"],"datasetMonitorId": "nike-de","datasetSourceNames": ["primary-export"],"datasetIsComplete": true,"mode": "monitor","outputMode": "changesOnly","verificationMode": "safe","stateNamespace": "agency-client-a"}
Schedule the upstream Task daily or weekly. When this monitor succeeds, read its
default Dataset and route rows where record_type = ad_event and
verification_status = CONFIRMED. The monitor status row remains available for
health checks even when no ad changed.
Use a distinct datasetMonitorId for each advertiser/query inventory and a
stable stateNamespace for each client or workflow. Serialize overlapping runs
for the same pair.
Run through the Apify API
curl "https://api.apify.com/v2/acts/automa-flow~tiktok-ads-dataset-monitor/runs" \-X POST \-H "Authorization: Bearer $APIFY_TOKEN" \-H "Content-Type: application/json" \--data-binary @input.json
Fetch result rows after the run succeeds:
curl "https://api.apify.com/v2/datasets/DATASET_ID/items?clean=true&format=json" \-H "Authorization: Bearer $APIFY_TOKEN"
Use the same stateNamespace and monitorId on every scheduled run. Changing
either starts a separate baseline.
Failure semantics
SUCCESS: at least one complete source produced usable ads;NOT_FOUND: at least one complete source validly produced zero ads;PARTIAL: data exists but no complete usable feed is available;FAILED: no feed could be verified or read.
A failed secondary source does not disable a complete primary source. It sets
coverageDegraded: true; safe mode still prevents uncorroborated changes from
being confirmed immediately. Dataset read errors, invalid rows, declared-total
mismatches and input limits never become an empty success.
State and limits
- compact state lives in the named Apify KVS
tiktok-ads-dataset-monitor-state; - each monitor has an isolated key derived from
stateNamespace + monitorId; - one feed may contain up to
maxItemsPerDatasetrows (default 5,000, maximum 10,000); - a Dataset beyond the configured cap is
PARTIAL, never truncated as success; - one state record is capped below 6 MiB; split very large inventories into country or advertiser monitors;
- no historical database and no media archive are created.
How much does TikTok ads monitoring cost?
Pay per event keeps quiet recurring checks cheap and makes large snapshots proportional to the output actually delivered. Actor platform usage is included; your upstream data provider or extractor is billed separately.
| Event | Price | Charged for |
|---|---|---|
monitor-check | $0.01 | One status row for a complete usable monitor or snapshot inventory, including a valid zero-ad result |
ad-event | $0.0001 | Each delivered snapshot, baseline, unchanged, candidate, or confirmed ad_event row |
| Realistic run | monitor-check | ad-event rows | Actor charge |
|---|---|---|---|
| Complete zero-ad or quiet repeat check | 1 | 0 | $0.0100 |
| Included one-ad first-run demo | 1 | 1 | $0.0101 |
| Check with 10 delivered changes | 1 | 10 | $0.0110 |
| 100-ad baseline or snapshot | 1 | 100 | $0.0200 |
| 1,000-ad baseline or snapshot | 1 | 1,000 | $0.1100 |
The formula is $0.01 × complete monitors + $0.0001 × delivered ad_event rows.
Snapshot and all output modes also bill every delivered ad_event row,
including UNCHANGED rows. Your upstream data provider or extractor is a
separate cost.
PARTIAL, FAILED, invalid input, Dataset reads, normalization, duplicates,
retries and internal work are not billed. There is no Actor-start charge. A
valid complete zero-ad result costs one inventory check because it still
produces a health row and a trustworthy NOT_FOUND outcome.
Set the run's maximum charge at or above the basket you expect. Delivery is
atomic per monitor: if the remaining limit cannot cover one monitor's status
and all of its event rows, that monitor emits one free BillingLimitReached
status, keeps its previous state, and makes the run fail explicitly. Completed
monitors earlier in the same batch remain delivered and saved.
The current price is the same for every Apify tier. The live Pricing tab is authoritative if prices change later.
Legal, privacy and source responsibility
This Actor processes data selected by the user. It does not grant rights to collect, store or redistribute the upstream data. Use only APIs, exports and Datasets you are authorized to use and review the upstream provider's terms.
The schema needs business-ad metadata, not viewer profiles, cookies or account credentials. Do not place access tokens or cookies inside observations. Media URLs are referenced, not downloaded, and may expire. The Actor is not affiliated with or endorsed by TikTok.
Frequently asked questions
Does this Actor scrape TikTok Ads Library?
No. It compares snapshots supplied by you or selected from Apify Datasets. Use an upstream source whose access and data terms permit your workflow.
How do I track new competitor TikTok ads?
Run the same complete advertiser or query inventory over time with a stable
monitorId and stateNamespace. The first run creates a baseline; later runs
emit NEW_AD candidates or confirmed events without re-emitting the full
inventory in changesOnly mode.
Can an empty Dataset mark every known ad inactive?
No. A complete zero-ad snapshot becomes NOT_FOUND, while failed or incomplete
inputs become FAILED or PARTIAL. Disappearance alone never marks an ad
inactive; the source must explicitly report active: false and be declared
authoritative for status.
Why are changes candidates before they are confirmed?
The default safe mode protects alerts from temporary upstream gaps and parser differences. A change is confirmed when two independent sources agree or the same complete primary source reports it on two consecutive runs. Choose fast mode only when one source already provides contractual completeness.
Can I replace the upstream TikTok Ads extractor later?
Yes. Keep stable ad IDs and monitor IDs, map the new provider's fields to any of the recognized aliases, and keep one stable primary source. The normalized output and last-successful-state contract do not depend on an extractor vendor.
Troubleshooting
| Symptom | What to check |
|---|---|
PARTIAL / IncompleteFeed | Enable the completeness field only after the upstream source finished every required page. |
FAILED / DatasetReadFailed | Re-select the Dataset in top-level datasetIds; do not use legacy feeds[].datasetId. |
| Every run creates a new baseline | Keep both stateNamespace and the monitor ID unchanged between runs. |
BillingLimitReached | Raise the run maximum to at least $0.01 + expected event rows × $0.0001 for that monitor. |
| Duplicate webhook alerts | Serialize runs for the same monitor and deduplicate by monitor_id + source_id + fingerprint + change_type. |
| No Slack or email arrives | This Actor creates alert-ready Dataset rows; connect them through an Apify integration, Make, n8n, or your webhook. |
Offline verification
uv run python actors/tiktok-ads-dataset-monitor/scripts/local_run.pyuv run pytest actors/tiktok-ads-dataset-monitor/tests
The local example makes no network requests and shows three runs: baseline, new-ad candidate and consecutive confirmation.
Known limitations
- upstream extraction quality and legality remain the user's/provider's responsibility;
- optional fields cannot be compared when the current source omits them;
- different providers may expose materially different semantics; keep one
stable primary source and inspect
sourceDisagreement; authoritativeStatusis a user assertion, not something this Actor can prove;- monitoring begins when the first successful baseline is stored; no historical backfill is inferred;
- this version sends no alerts itself—use Dataset integrations, schedules and webhooks;
- overlapping runs for the same
stateNamespace + monitorIdare not supported; serialize them to avoid duplicate alerts or last-writer-wins KVS updates; - Dataset delivery and named-KVS state are separate Apify writes. If a rare state-save failure happens after rows were delivered, the run fails and the prior state remains; inspect the delivered Dataset before rerunning and use the stable deduplication key documented above.