# Ad Library Scraper by Domain: AI Briefs, Live Ads and Ad Data (`classy_truth/upspring-ad-intelligence`) Actor

Paste a list of domains, get each advertiser's AI-analyzed brief, live ads: creative text, media and landing URLs, days running, plus grades.

- **URL**: https://apify.com/classy_truth/upspring-ad-intelligence.md
- **Developed by:** [Ron Dahan](https://apify.com/classy_truth) (community)
- **Categories:** Lead generation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $50.00 / 1,000 advertiser lookups

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

## Upspring Ad Intelligence

Turn domains into ad intelligence: AI-analyzed briefs, active ads, top creatives, landing pages, and spend, traffic and sales grades, one row per company.

### What does Upspring Ad Intelligence do?

Give it a list of domains and it returns one row per domain with the advertiser's live ads. You get the advertiser name, how many ads are active, when they were first and last seen, coarse spend, traffic and sales grades, and the top ads with creative text, media URL, landing URL, CTA and days running.

Every advertiser is analyzed with AI: its ads (including video and image creative) are aggregated through a visual model to produce a short brief about the advertiser's positioning, target audience, hook strategies, and persuasion mechanisms. This gives you the strategic context behind the ads, not just raw creative.

Upspring Ad Intelligence turns a list of company domains into one clean row each: advertiser name, active ads count, first and last seen, spend, traffic and sales grades, AI-analyzed brief about positioning and audience, top personas and hooks, and the top ads with creative text, media URL, landing page, CTA and days running. Use it to qualify leads, personalize outreach with strategic insights from the brief, or track competitors without scraping a single ad library. You pay $0.05 per domain that returns ads, and nothing for domains with no ads. Grades are coarse modeled tiers, never exact figures.

### How do I get ad data by domain?

Pass a list of domains. The Actor normalizes them (strips protocols, www, paths), looks up each advertiser in Upspring's ad intelligence corpus, and returns one row per domain. Each row includes the advertiser's AI-analyzed brief, top personas and hooks, active ads count, spend, traffic and sales grades, and the top-performing ads with creative text, media URLs, landing pages, CTAs, and days running.

**AI Analysis**: Each advertiser has been analyzed with a visual model that processes ads (video and image) to generate a short summary brief. You get the advertiser's positioning, target personas, hook strategies, and persuasion mechanisms in addition to the raw ad data.

```json
{
  "domains": ["example-brand.com", "sample-company.com", "test-business.com"],
  "maxAdsPerDomain": 25,
  "activeOnly": true,
  "detailAds": 5
}
```

**Output** (one row per domain):

```json
{
  "domain": "example-brand.com",
  "status": "ready",
  "advertiser_name": "Example Brand",
  "advertiser_id": "123456789",
  "active_ads_count": 45,
  "first_seen": "2026-09-15T10:00:00.000Z",
  "last_seen": "2026-10-30T18:30:00.000Z",
  "spend_grade": "B",
  "traffic_grade": "A",
  "sales_grade": "C",
  "summary": {
    "one_line": "Example Brand positions itself as a value optimizer in home goods, offering premium alternatives at accessible prices.",
    "short_summary": "Example Brand targets budget-conscious shoppers in the US market by combining quality claims with aggressive promotional pricing. The brand's dominant playbook involves problem-solution framing and product demonstrations to highlight its alternatives as superior to traditional options."
  },
  "vertical": "Home Goods",
  "category": "Kitchen Storage",
  "ad_signals": {
    "personas": [
      { "label": "The Deal-Seeker", "share": 0.42 },
      { "label": "Optimizer", "share": 0.31 },
      { "label": "The Practical Parent", "share": 0.18 }
    ],
    "hooks": [
      { "label": "Problem statement", "share": 0.35 },
      { "label": "Bold claim", "share": 0.28 },
      { "label": "Question", "share": 0.22 }
    ],
    "mechanisms": [
      { "label": "Problem amplify → relieve", "share": 0.38 },
      { "label": "Pricing-as-positioning", "share": 0.29 },
      { "label": "Demonstration-as-claim", "share": 0.21 }
    ],
    "media_mix": { "label": "Video", "share": 0.78 },
    "funnel": { "label": "Consideration", "share": 0.52 }
  },
  "top_ads": [
    {
      "ad_id": "abc123",
      "platform": "Facebook",
      "creative_text": "Transform your kitchen with premium storage solutions",
      "media_url": "https://storage.example.com/video.mp4",
      "landing_url": "https://example-brand.com/shop",
      "cta": "Shop Now",
      "days_running": 45,
      "rank": 1
    }
  ],
  "upspring_url": "https://upspring.ai"
}
```

Add domains, run the Actor, read the dataset or call it from the API.

### What data do I get for each domain?

| Field | Description |
|-------|-------------|
| **Advertiser name** | Brand name from the ad account |
| **Active ads count** | Total number of currently running ads |
| **First seen / Last seen** | Earliest and most recent ad start dates |
| **Spend grade** | Coarse modeled spending tier (D, C, B, A, A+) |
| **Traffic grade** | Coarse modeled traffic tier (D, C, B, A, A+) |
| **Sales grade** | Coarse modeled sales tier (D, C, B, A, A+) |
| **Summary** | AI-generated one-line and short summary analyzing positioning and strategy |
| **Vertical / Category** | Business vertical and category (e.g., Kitchen Dining / Food Storage) |
| **Ad signals** | AI-analyzed top personas, hooks, mechanisms, media mix, and funnel stage |
| **Top ads** | Array of top-performing ads with creative text, media URL, landing URL, CTA, and days running |

### Is this an ad library scraper or a competitor ad intelligence API?

It returns live ads for any advertiser by domain, so yes, you can use it for ad library lookups and competitor research. Supported sources: Meta Ad Library (Facebook).

### How much does it cost?

$0.05 per domain that returns ads. $0.002 for each extra ad beyond 25 per domain. Domains with no ads cost nothing.

**Example**: 100 domains where 80 return ads = $4.00 (plus $0.002 for each ad beyond the first 25 per domain, if any).

### How do I use it with Claude or ChatGPT?

1. Run the Actor via the Apify MCP server or API
2. Pass the dataset to your AI model
3. Ask it about hooks, offers, landing pages and how long ads have been running

This turns live ads into context an AI can read, which is the idea behind [Upspring](https://upspring.ai).

### How accurate are the grades?

Spend, traffic and sales grades are coarse modeled tiers, not exact figures. Use them to compare advertisers, not to read off budgets or revenue.

### Use Cases

**Qualify leads by ad activity.** Run your prospect list through the Actor and keep only the companies actively advertising. Sort by spend grade to reach the ones with real budget first.

**Personalize outreach with AI briefs.** Pull each prospect's AI-analyzed summary, top personas and hooks, and reference their positioning strategy in your email or DM. Open with something specific from their brief, not just a generic compliment.

**Watch competitors.** Schedule a weekly run on a competitor list and spot new ads, new offers and ads that have been running for a long time (usually the winners).

### FAQ

**How fresh is the data?**
The Actor fetches live data from Upspring's API on every run. Ads are refreshed regularly on the platform side.

**How many ads per domain?**
By default, you get up to 25 top-performing ads per domain. Set `maxAdsPerDomain` (max 100) to fetch more. The first 25 are included in the base charge. Additional ads cost $0.002 each.

**What if a domain has no ads?**
Domains with no ads return a row with `status: "no_ads"` and zero charge.

**Can I export to CSV or Google Sheets?**
Yes. Download the dataset as CSV from the Apify Console, or connect the Actor to Google Sheets via Apify integrations.

**Can I call it from the API?**
Yes. Use the Apify API to run the Actor and fetch results programmatically. See the [Apify API documentation](https://docs.apify.com/api/v2).

### Input

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `domains` | array | required | List of website domains (protocol, www, paths stripped automatically) |
| `country` | string | optional | Filter by country (not currently supported by the API) |
| `maxAdsPerDomain` | integer | 25 | Maximum ads per domain (1-100). First 25 included in base charge. |
| `activeOnly` | boolean | true | Fetch only currently active ads |
| `detailAds` | integer | 5 | Number of top ads to fetch full details for (CTA, landing URL). Max 25. |
| `maxWaitSecondsPerDomain` | integer | 30 | Maximum time in seconds to wait for pending domains (5-120). Domains still pending after this time return status 'pending' and are not charged. |

### Output

One dataset row per domain:

| Field | Type | Description |
|-------|------|-------------|
| `domain` | string | Normalized input domain |
| `status` | string | `ready`, `pending`, `no_ads`, or `error` |
| `advertiser_name` | string | Brand name |
| `advertiser_id` | string | Upspring advertiser ID |
| `active_ads_count` | integer | Total currently active ads |
| `first_seen` | string | ISO 8601 timestamp of earliest ad |
| `last_seen` | string | ISO 8601 timestamp of most recent ad |
| `spend_grade` | string | Spending tier (D, C, B, A, A+) |
| `traffic_grade` | string | Traffic tier (D, C, B, A, A+) |
| `sales_grade` | string | Sales tier (D, C, B, A, A+) |
| `summary` | object | AI-generated summary analyzing positioning and strategy |
| `summary.one_line` | string | One-line summary of positioning |
| `summary.short_summary` | string | Short paragraph analyzing strategy, audience, and creative approach |
| `vertical` | string | Business vertical (e.g., Kitchen Dining, Health Beauty) |
| `category` | string | Business category (e.g., Food Storage, Skincare) |
| `ad_signals` | object | AI-analyzed ad signals |
| `ad_signals.personas` | array | Top 3 target personas with label and share (0-1, 2 decimals) |
| `ad_signals.hooks` | array | Top 3 hook types with label and share (0-1, 2 decimals) |
| `ad_signals.mechanisms` | array | Top 3 persuasion mechanisms with label and share (0-1, 2 decimals) |
| `ad_signals.media_mix` | object | Primary media format (Video or Image) with share |
| `ad_signals.funnel` | object | Primary funnel stage (Awareness, Consideration, Conversion) with share |
| `top_ads` | array | Top-performing ads with creative data |
| `upspring_url` | string | Link to Upspring platform |
| `error_message` | string | Error description (only when status is `error`) |

#### Top Ads Structure

Each ad in `top_ads` includes:

| Field | Type | Description |
|-------|------|-------------|
| `ad_id` | string | Upspring ad ID |
| `platform` | string | Platform where ad ran (Facebook, or null) |
| `creative_text` | string | Hook text or one-line summary |
| `media_url` | string | Video, image, or thumbnail URL |
| `landing_url` | string | Landing page URL (top N ads only) |
| `cta` | string | Call-to-action text (top N ads only) |
| `days_running` | integer | Days since ad started |
| `rank` | integer | Rank in top ads list |

### Configuration

Set these environment variables in Apify Console under Actor Settings > Environment variables:

**Required:**

- `UPSPRING_API_KEY`: Your Upspring API key (prefixed `upk_...`). The Actor will fail immediately if not set.

**Optional (Analytics):**

- `POSTHOG_API_KEY`: PostHog project API key for usage tracking (silent no-op if unset)
- `POSTHOG_HOST`: PostHog API host (default: `https://us.i.posthog.com`)

### Limitations

- **Platform support**: Only Meta Ad Library (Facebook) is currently detected. Other platforms return `platform: null`.
- **Landing URLs and CTAs**: Available for the top N ads only (default 5, controlled by `detailAds`). Other ads have these fields set to `null`.
- **Last seen**: Derived from most recent ad start date, not a true "stopped running" timestamp.
- **Country filtering**: Not currently supported by the underlying API.

### Pricing

**Pay-per-result model:**

- **$0.05** per domain that returns ads (includes first 25 ads)
- **$0.002** per additional ad beyond 25
- **$0.00** for domains with no ads, errors, or pending status

No additional charges for detail fetching (landing URLs, CTAs).

### Support

For Actor issues, open an issue in the repository. For Upspring API questions, see https://public-api.upspring.ai/v1/docs/ui.

Deployment instructions and technical details are in `DEPLOY.md`.

# Actor input Schema

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

List of website domains to fetch ad intelligence for. Domains will be normalized (protocol, www, paths stripped, lowercased). Example: \['example-brand.com', 'sample-company.com']

## `country` (type: `string`):

Filter advertisers by country if supported by the API. Leave empty for all countries.

## `maxAdsPerDomain` (type: `integer`):

Maximum number of top ads to fetch per domain (default: 25). Additional ads beyond the first 25 are charged at $0.002 per ad.

## `activeOnly` (type: `boolean`):

Fetch only currently active ads (default: true). Set to false to include stopped ads.

## `detailAds` (type: `integer`):

Fetch detailed information (CTA, landing URL) for the top N ads per domain (default: 5). Set to 0 to skip detail fetching.

## `maxWaitSecondsPerDomain` (type: `integer`):

Maximum time to wait for each domain's advertiser data to be ready (default: 30 seconds). If the domain is still pending after this time, it will be returned with status 'pending' and not charged.

## Actor input object example

```json
{
  "domains": [
    "example-brand.com"
  ],
  "maxAdsPerDomain": 25,
  "activeOnly": true,
  "detailAds": 5,
  "maxWaitSecondsPerDomain": 30
}
```

# Actor output Schema

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

Dataset with one row per domain.

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

Dataset overview with key columns.

# 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": [
        "example-brand.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("classy_truth/upspring-ad-intelligence").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": ["example-brand.com"] }

# Run the Actor and wait for it to finish
run = client.actor("classy_truth/upspring-ad-intelligence").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": [
    "example-brand.com"
  ]
}' |
apify call classy_truth/upspring-ad-intelligence --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,classy_truth/upspring-ad-intelligence"
        }
    }
}
```

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/dgzUzUjKkskXEyxE4/builds/tMxZ49Acv0ArhdVGO/openapi.json
