# TikTok & Kwai Ad Pixel Checker (`automation-lab/tiktok-kwai-domain-advertiser-checker`) Actor

Check public company domains for TikTok and Kwai ad pixel signals, IDs, detection paths, GTM evidence, and fetch diagnostics.

- **URL**: https://apify.com/automation-lab/tiktok-kwai-domain-advertiser-checker.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Lead generation, Social media
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.92 / 1,000 domain extracteds

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## TikTok & Kwai Ad Pixel Checker

Turn a list of public company domains into evidence-based TikTok and Kwai advertiser signals.

This ad pixel checker inspects each public homepage and a bounded number of referenced public Google Tag Manager (GTM) containers.
It exports one row per submitted domain with separate network verdicts, exposed pixel IDs, detection paths, source URLs, and fetch diagnostics.

Use the results to qualify prospects, research competitors, audit campaign setup, or refresh an advertiser-enrichment table.

### What does this Actor do?

The Actor accepts plain domains such as `apify.com` and complete HTTP(S) URLs.
For each entry it:

1. normalizes the URL;
2. validates that every destination is public;
3. fetches the page with bounded redirects and retries;
4. detects TikTok and Kwai script URLs, JavaScript APIs, variables, and exposed IDs;
5. discovers referenced `GTM-*` container IDs;
6. optionally checks a bounded number of public GTM container scripts;
7. exports independent TikTok and Kwai verdicts;
8. includes diagnostics that distinguish a clean no-signal result from an unreachable page.

A `detected` verdict means a supported public signature was found.
A `no-signal` verdict means the page was fetched successfully but no supported signature was visible.
An `unknown` verdict means the page could not be evaluated reliably.

### Who is it for?

**Lead-generation teams** can prioritize companies whose sites expose TikTok or Kwai campaign infrastructure.

**Advertising agencies** can find public evidence relevant to outreach and account audits.

**Competitive-intelligence teams** can compare current pixel presence across a watchlist.

**Marketing operations teams** can check whether an expected tag is publicly visible after a deployment.

**Data teams** can enrich domain tables through the API and schedule recurring snapshots.

This Actor is focused on TikTok and Kwai qualification.
Choose a broader technology-stack Actor when you need CMS, analytics, hosting, or dozens of unrelated trackers.

### Why use it?

- One stable row per submitted entry.
- Separate TikTok and Kwai verdicts instead of one ambiguous tracker flag.
- Pixel IDs when the public implementation exposes them.
- Detection paths that explain why a verdict is positive.
- Source URLs showing whether evidence came from page HTML or GTM.
- Bounded GTM inspection without running a full browser.
- Explicit HTTP, content-type, size, retry, and timing diagnostics.
- SSRF defenses that reject credentials, local hosts, and private network addresses.
- Conservative concurrency and finite retries for predictable runs.

### Input

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `domains` | array | required | Up to 1,000 public domains or HTTP(S) URLs. |
| `scanGtmContainers` | boolean | `true` | Inspect referenced public GTM container JavaScript. |
| `maxGtmContainersPerDomain` | integer | `3` | Maximum GTM containers fetched per domain, from 0 to 10. |
| `maxConcurrency` | integer | `5` | Concurrent domain checks, from 1 to 20. |
| `requestTimeoutSecs` | integer | `20` | Timeout per request, from 5 to 60 seconds. |

Plain domains are normalized to HTTPS.
Complete URLs may include a public path.
URLs containing credentials are rejected.
Localhost, local domains, and private IP destinations are rejected.

#### Small input example

```json
{
  "domains": [
    "neo-ia.eu",
    "stanleyshair.com",
    "apify.com"
  ],
  "scanGtmContainers": true,
  "maxGtmContainersPerDomain": 3,
  "maxConcurrency": 3
}
```

### Output fields

| Field | Meaning |
| --- | --- |
| `domain` | Normalized hostname. |
| `inputUrl` | Normalized submitted URL. |
| `finalUrl` | URL after validated public redirects. |
| `checkedAt` | UTC completion time. |
| `tiktokDetected` | Convenience boolean for a TikTok detection. |
| `tiktokVerdict` | `detected`, `no-signal`, or `unknown`. |
| `tiktokPixelIds` | Publicly exposed TikTok pixel IDs. |
| `tiktokDetectionPaths` | Matched signature and extraction path. |
| `tiktokSourceUrls` | URLs containing TikTok evidence. |
| `kwaiDetected` | Convenience boolean for a Kwai detection. |
| `kwaiVerdict` | `detected`, `no-signal`, or `unknown`. |
| `kwaiPixelIds` | Publicly exposed Kwai pixel IDs. |
| `kwaiDetectionPaths` | Matched signature and extraction path. |
| `kwaiSourceUrls` | URLs containing Kwai evidence. |
| `gtmContainerIds` | Referenced public GTM IDs. |
| `scannedSourceUrls` | Every page or GTM URL inspected. |
| `fetchStatus` | Fetch or input-validation outcome. |
| `httpStatus` | Final page HTTP status when available. |
| `contentType` | Final response content type. |
| `responseBytes` | Number of analyzed response bytes. |
| `elapsedMs` | Total domain-check duration. |
| `retryCount` | Transient retries across the check. |
| `error` | Concise diagnostic when evaluation failed. |

All schema fields are nullable because public sites can change or omit evidence.
Arrays are empty when no corresponding public evidence was found.

### Output example

A current direct-page TikTok detection can look like this:

```json
{
  "domain": "neo-ia.eu",
  "inputUrl": "https://neo-ia.eu/",
  "finalUrl": "https://neo-ia.eu/",
  "tiktokDetected": true,
  "tiktokVerdict": "detected",
  "tiktokPixelIds": ["CVLSKRBC77UB7DSGH6Q0"],
  "tiktokDetectionPaths": [
    "page HTML: analytics.tiktok.com pixel script",
    "page HTML: ttq JavaScript API",
    "page HTML: TikTok pixel ID"
  ],
  "kwaiDetected": false,
  "kwaiVerdict": "no-signal",
  "kwaiPixelIds": [],
  "gtmContainerIds": [],
  "fetchStatus": "success",
  "httpStatus": 200,
  "retryCount": 0,
  "error": null
}
```

Public tags can change after this example is written.
Use the current run output as the authoritative observation.

### How much does it cost to check domains for TikTok and Kwai pixels?

Pricing uses pay per event:

- a one-time **Start** event of **$0.005** per run;
- one **Domain extracted** event per submitted entry;
- the BRONZE domain price is **$0.0032 per domain**.

GTM evidence and diagnostics are included in the domain event.
They are not charged as separate records.

Example BRONZE totals:

| Domains | Start | Domain events | Estimated total |
| ---: | ---: | ---: | ---: |
| 1 | $0.005 | $0.0032 | $0.0082 |
| 10 | $0.005 | $0.032 | $0.037 |
| 100 | $0.005 | $0.320 | $0.325 |

Higher subscription tiers receive the active tier price shown in Apify Console.
Actual billing follows the active platform pricing for your account tier.

### Getting started

1. Open the Actor in Apify Console.
2. Add one or more public domains to **Company domains**.
3. Keep **Scan public GTM containers** enabled for broader public evidence.
4. Start with the default concurrency.
5. Click **Start**.
6. Open the default dataset.
7. Filter `tiktokVerdict` or `kwaiVerdict` to `detected`.
8. Export the result as JSON, CSV, Excel, XML, or RSS.
9. Schedule the task when you need recurring snapshots.

### Detection behavior

TikTok checks include public `analytics.tiktok.com` pixel scripts, the `ttq` JavaScript API, common TikTok pixel variables, and exposed loader IDs.

Kwai checks include public Kwai pixel script URLs, the `kwaiq` JavaScript API, common Kwai pixel variables, and exposed loader IDs.

The Actor also extracts public GTM container IDs from successful page HTML.
When enabled, it fetches each bounded container from `www.googletagmanager.com` and applies the same network-specific checks.

A positive signature is evidence of tag code, not proof that an advertising campaign is currently spending money.
A pixel may be dormant, conditionally triggered, misconfigured, or loaded only after consent.

### Recurring advertiser qualification

Create an Apify Task with your CRM or prospecting domains.
Schedule it daily, weekly, or monthly.
Export each run to your destination or retrieve it through the dataset API.

A useful downstream workflow is:

1. join rows to the normalized `domain` key;
2. keep `detected` and `no-signal` distinct from `unknown`;
3. compare pixel ID arrays between snapshots;
4. route newly detected domains to research;
5. retry unknown domains later rather than treating them as negatives.

The Actor emits observations only.
It does not maintain historical state or send change alerts itself.

### API with cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~tiktok-kwai-domain-advertiser-checker/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"domains":["neo-ia.eu","stanleyshair.com"],"scanGtmContainers":true}'
```

To wait for completion and receive dataset items:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~tiktok-kwai-domain-advertiser-checker/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"domains":["apify.com"]}'
```

Keep your token in a secret or environment variable.
Do not commit it to source control.

### API with JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/tiktok-kwai-domain-advertiser-checker').call({
    domains: ['neo-ia.eu', 'stanleyshair.com'],
    scanGtmContainers: true,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### API with Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/tiktok-kwai-domain-advertiser-checker').call(
    run_input={
        'domains': ['neo-ia.eu', 'stanleyshair.com'],
        'scanGtmContainers': True,
    }
)
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)
```

### Use with Apify MCP

Add the Actor to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/tiktok-kwai-domain-advertiser-checker"
```

Claude Desktop, Cursor, and VS Code can use this equivalent MCP JSON configuration:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/tiktok-kwai-domain-advertiser-checker"
    }
  }
}
```

Example prompts:

- “Check these domains for TikTok and Kwai pixels and summarize detected IDs.”
- “Separate successful no-signal checks from unknown fetch failures.”
- “Return the GTM detection path for every Kwai-positive domain.”

### Integrations

Use Apify integrations to send result rows to Google Sheets, Slack, Zapier, Make, webhooks, or cloud storage.

For CRM enrichment, keep `domain` as the join key and retain the verdict plus diagnostics.

For spreadsheets, export the overview view for compact columns.
Use JSON when you need the complete evidence arrays.

For scheduled monitoring, store each run timestamp and compare snapshots downstream.

### Reliability, retries, and limits

Each request has a configurable timeout.
Transient network errors, rate limits, and selected server errors receive at most two retries with backoff.
Redirects are limited and every redirect destination is validated again.

The Actor analyzes at most 5 MB of text from each response.
It scans only the submitted URL, not every page on the domain.
It checks at most the configured number of GTM containers.

A blocked page returns an `unknown` network verdict with diagnostics.
The Actor does not silently convert a failed fetch into `no-signal`.

### Limitations

- It checks public source available without login.
- It does not prove active media spend.
- Consent-gated tags may not appear in a direct HTTP response.
- Browser-only tags triggered by interaction may be absent.
- Server-side conversion APIs cannot be detected from public browser code.
- Obfuscated or custom proxy loaders may not match supported signatures.
- A site can block automated requests or return different regional HTML.
- Only the submitted page and bounded public GTM containers are inspected.
- The Actor does not crawl checkout, confirmation, or campaign landing pages automatically.

Treat `no-signal` as “not visible in the checked public sources,” not “definitely never used.”

### Legality and responsible use

Only submit public websites you are permitted to access.
Respect applicable website terms, robots guidance, rate limits, privacy law, and advertising-platform policies.

The output reports technical signals exposed by public pages.
Do not use it to infer sensitive personal traits, evade access controls, or make automated high-impact decisions about individuals.

Avoid combining pixel evidence with personal data unless you have a lawful purpose and appropriate safeguards.

### Troubleshooting

#### Why is the verdict `unknown`?

Inspect `fetchStatus`, `httpStatus`, and `error`.
The page may have blocked the request, timed out, redirected to an invalid destination, or returned a non-text response.
Retry later before classifying the domain.

#### Why is a known pixel reported as `no-signal`?

The tag may load only after consent, interaction, authentication, geolocation, or client-side rendering.
Try the precise public landing-page URL where you expect the tag.
This Actor intentionally does not claim browser-only coverage.

#### Why is a GTM ID listed but no network pixel detected?

A container can omit the pixel, trigger it only under conditions, or retrieve later configuration from another service.
The GTM ID itself is diagnostic context, not a TikTok or Kwai verdict.

#### Why is a pixel ID empty on a detected row?

Some public signatures call a network API without exposing the ID in a supported literal format.
The detection paths and source URLs still explain the positive signature.

### FAQ

#### Does this scan Meta or Google Ads pixels?

No.
The output contract is intentionally focused on TikTok and Kwai.

#### Does it support bulk checks?

Yes.
Submit up to 1,000 domains per run and tune concurrency between 1 and 20.

#### Does it use residential proxies?

No automatic paid proxy fallback is enabled.
The Actor uses direct public HTTP requests and reports blocked pages as unknown.

#### Are GTM containers public?

The Actor fetches only container JavaScript referenced by the submitted public page from Google's public GTM host.
It does not access a GTM account or private workspace.

#### Can I schedule it?

Yes.
Save the input as an Apify Task and configure a schedule in Console.
Store or export snapshots if you need change history.

#### Is every result charged?

One Domain extracted event is charged for each submitted entry because the verdict and diagnostics are the result, including an explicit unknown or invalid-input outcome.
There is no separate charge for GTM sources or pixel IDs.

### Related Automation Lab Actors

- [Bulk DMARC Record Checker](https://apify.com/automation-lab/bulk-dmarc-record-checker) adds email-security posture to domain qualification.
- [Domain Registration & RDAP Lookup](https://apify.com/automation-lab/domain-rdap-lookup) adds registration dates, registrar, status, and nameserver evidence.
- [Flexible HTTP Request Runner](https://apify.com/automation-lab/flexible-http-request-runner) supports custom public endpoint polling when you need a general HTTP workflow instead of opinionated pixel detection.

Combine these Actors downstream when a prospecting workflow needs advertising, domain-registration, email-security, and custom endpoint signals.

### Support

For reproducible problems, include a sanitized input, run URL, affected domain, expected verdict, and the relevant diagnostic fields.
Do not include API tokens, cookies, private URLs, or credentials.

# Actor input Schema

## `domains` (type: `array`):

Public domains or HTTP(S) URLs to check. Plain domains such as apify.com are accepted.

## `scanGtmContainers` (type: `boolean`):

Fetch referenced public Google Tag Manager container JavaScript and inspect it for TikTok and Kwai signatures.

## `maxGtmContainersPerDomain` (type: `integer`):

Bound the number of referenced GTM containers fetched for each domain.

## `maxConcurrency` (type: `integer`):

Number of company domains checked concurrently.

## `requestTimeoutSecs` (type: `integer`):

Timeout for each page or GTM-container fetch before bounded retry handling.

## Actor input object example

```json
{
  "domains": [
    "neo-ia.eu",
    "stanleyshair.com",
    "apify.com"
  ],
  "scanGtmContainers": true,
  "maxGtmContainersPerDomain": 3,
  "maxConcurrency": 5,
  "requestTimeoutSecs": 20
}
```

# Actor output Schema

## `overview` (type: `string`):

Default dataset items rendered through the compact domain-verdict overview.

# 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 = {
    "domains": [
        "neo-ia.eu",
        "stanleyshair.com",
        "apify.com"
    ],
    "scanGtmContainers": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/tiktok-kwai-domain-advertiser-checker").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 = {
    "domains": [
        "neo-ia.eu",
        "stanleyshair.com",
        "apify.com",
    ],
    "scanGtmContainers": True,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/tiktok-kwai-domain-advertiser-checker").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 '{
  "domains": [
    "neo-ia.eu",
    "stanleyshair.com",
    "apify.com"
  ],
  "scanGtmContainers": true
}' |
apify call automation-lab/tiktok-kwai-domain-advertiser-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/tiktok-kwai-domain-advertiser-checker"
        }
    }
}
```

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/cYUAFoGdOM0Tymtx6/builds/pqeXVtH2GIRX1hC6I/openapi.json
