# Proxy Docs

> Proxy is an MCP server that gives AI assistants live access to the Meta, Google, LinkedIn and TikTok ad libraries.

# Introduction
Source: https://useproxy.dev/docs

**[Quickstart](/docs/quickstart)**

Connect in under two minutes and run your first competitor query.

**[Connect your client](/docs/clients)**

Claude, ChatGPT, Claude Code, Cursor, Codex, Copilot, Zed and the CLI installer.

**[Authentication](/docs/authentication)**

OAuth 2.0 with PKCE and dynamic client registration. How the 401 handshake works.

**[Tool reference](/docs/tools/meta-ads)**

Every tool, its parameters, and what it returns.

**[Credits and plans](/docs/credits)**

Free tier, daily limits, and what each call costs.

**[Sandbox](/docs/sandbox)**

Fixture ad data with no account, for testing and auditors.

## What Proxy does

Ad library websites show one ad at a time with no analysis. Proxy exposes those libraries as MCP tools, so an assistant can pull hundreds of ads across brands and platforms in one conversation, transcribe the videos, and explain the hooks, offers and formats that are working.

- **Meta Ad Library** for Facebook and Instagram, by brand or by keyword
- **Google Ads Transparency Center** by domain or advertiser ID, with per-ad creative variations
- **LinkedIn Ad Library** by company, keyword or company ID, with targeting and impression data
- **TikTok EU DSA repository** by registered advertiser name
- **Analysis tools** for image vision, video transcription, competitor discovery and cross-platform briefs

## How it connects

Proxy is a single remote MCP server over Streamable HTTP:

```text
https://mcp.useproxy.dev/mcp
```

There is no REST API and no OpenAPI spec. Any MCP client connects to that URL, signs in through OAuth on first use, and then calls tools directly. See [Connect your client](/docs/clients).

## Who it is for

- Marketers and founders doing competitor research inside ChatGPT or Claude
- Agencies building creative swipe files across many brands at once
- Agent builders who want ad library data as a native tool

:::note
Proxy only returns public ad library data. It cannot see dark posts, unpublished ads, spend, CPM or CPC.
:::

---

# Authentication
Source: https://useproxy.dev/docs/authentication

## Overview

There are no API keys to create or paste. Proxy is an OAuth 2.0 protected resource, and MCP clients discover and complete the flow on their own.

| Step | What happens |
| --- | --- |
| 1 | Client sends a request to `/mcp` without a token and receives **401** |
| 2 | The `WWW-Authenticate` header names the protected resource metadata URL |
| 3 | Client reads the metadata, finds the authorization server, and registers itself (dynamic client registration) |
| 4 | Client opens the browser for sign-in with PKCE |
| 5 | Client retries with a bearer token; tools now work |

## Discovery endpoints

| Document | URL |
| --- | --- |
| Protected resource metadata (RFC 9728) | `https://mcp.useproxy.dev/.well-known/oauth-protected-resource/mcp` |
| Authorization server metadata (RFC 8414) | `https://mcp.useproxy.dev/.well-known/oauth-authorization-server` |
| Resource identifier | `https://mcp.useproxy.dev/mcp` |

## The 401 handshake

An unauthenticated `initialize` is expected to fail. This is the spec, not an outage:

```http
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer error="invalid_token",
  resource_metadata="https://mcp.useproxy.dev/.well-known/oauth-protected-resource/mcp"
```

A compliant client follows `resource_metadata` and completes OAuth before retrying. Clients that never read that header cannot connect to any spec-compliant MCP server.

## Redirect URIs

Dynamic client registration is open. A registration is accepted with any redirect URI, but `authorize` only completes for URIs that match an allowed pattern for known clients (Claude, ChatGPT, Cursor, Codex, Copilot, Zed, MCP Inspector, localhost). If your client is rejected at authorize time, contact [support@useproxy.dev](mailto:support@useproxy.dev) with the redirect URI.

## Personal tokens

The [CLI installer](/docs/clients#cli-installer-any-client) runs the browser flow once and issues a long-lived personal bearer token (prefix `proxy_`). Send it as `Authorization: Bearer <token>` on `/mcp`. Use it for clients that cannot open a browser or for scripted agents.

:::note
Personal tokens are scoped to one account and do not expire. Re-running the installer replaces the previous token; there is no self-serve revoke yet, so email support to kill a leaked token.
:::

## Reference

The agent-facing version of this page, in plain markdown, is at [/auth.md](https://useproxy.dev/auth.md).

---

# Connect your client
Source: https://useproxy.dev/docs/clients

Every client talks to the same endpoint over Streamable HTTP.

```text
https://mcp.useproxy.dev/mcp
```

## Claude (web and desktop)

Customize, then Connectors, then **Add custom connector**. Paste the endpoint URL. Claude runs the OAuth flow on first use. Direct link: [claude.ai/customize/connectors](https://claude.ai/customize/connectors?modal=add-custom-connector).

## ChatGPT

Search **Proxy** in the App store, or Settings, then Apps and Connectors, then Create with the endpoint URL. Direct link: [chatgpt.com/#settings/Connectors](https://chatgpt.com/#settings/Connectors).

:::note
ChatGPT Instant mode calls tools but does not render inline widgets. Use normal mode for the ad carousel.
:::

## Claude Code

```bash
claude mcp add --transport http proxy https://mcp.useproxy.dev/mcp
```

## Codex

```bash
codex mcp add proxy --url https://mcp.useproxy.dev/mcp
```

## Cursor

Add to `~/.cursor/mcp.json` or the project `.cursor/mcp.json`:

```json
{ "mcpServers": { "proxy": { "url": "https://mcp.useproxy.dev/mcp" } } }
```

## GitHub Copilot

Add to `.vscode/mcp.json`:

```json
{ "servers": { "proxy": { "type": "http", "url": "https://mcp.useproxy.dev/mcp" } } }
```

## Zed

Add to `settings.json`:

```json
{ "context_servers": { "proxy": { "url": "https://mcp.useproxy.dev/mcp" } } }
```

## CLI installer (any client)

The installer runs the OAuth flow in your browser, mints a personal bearer token, and writes config for every client it finds on the machine.

```bash
curl -sL useproxy.dev/install | sh
```

Source: [useproxy.dev/install](https://useproxy.dev/install). Tokens issued this way work for clients that cannot open a browser. To rotate one, re-run the installer; to revoke without replacing, email [support@useproxy.dev](mailto:support@useproxy.dev).

## Directories

Proxy is also listed on [Smithery](https://smithery.ai/servers/useproxy/proxy), [Glama](https://glama.ai/mcp/connectors/dev.useproxy/proxy) and the [official MCP registry](https://registry.modelcontextprotocol.io/v0/servers?search=dev.useproxy) as `dev.useproxy/proxy`.

## Machine-readable setup

The same per-client snippets are published in the manifest at [/.well-known/mcp.json](https://useproxy.dev/.well-known/mcp.json) under `clients`.

---

# Credits and plans
Source: https://useproxy.dev/docs/credits

## How credits work

- One credit per ad-library or analysis call. Batch calls cost one per item.
- Searches that auto-paginate upstream cost one credit per page fetched. TikTok search fetches up to five pages, so one call can cost up to five credits.
- `get_credit_balance` and `get_competitive_brief` are free.
- Credits reset daily. Unused credits do not roll over.
- At the cap, the tool returns an upgrade link. Nothing is billed automatically.

## Plans

| Plan | Price | Credits per day |
| --- | --- | --- |
| Free | $0 | 20 |
| Pro | $50 / month | 100 |
| Max | $100 / month | 250 |

Annual billing gives two months free on every paid tier. Full details on the [pricing page](https://useproxy.dev/pricing) or in [pricing.md](https://useproxy.dev/pricing.md).

## Self-serve

Sign-up happens inside the OAuth flow on first connect. Upgrades go through a checkout link returned by `get_credit_balance` or from the [account page](https://mcp.useproxy.dev/me/site). No sales call.

## Checking balance

Ask the assistant "how many Proxy credits do I have left" or call `get_credit_balance` directly.

---

# Quickstart
Source: https://useproxy.dev/docs/quickstart

## 1. Add the server

Pick your client. Full instructions for every client are in [Connect your client](/docs/clients).

```bash
# Claude Code
claude mcp add --transport http proxy https://mcp.useproxy.dev/mcp

# Codex
codex mcp add proxy --url https://mcp.useproxy.dev/mcp

# Anything else: detects installed clients and writes their config
curl -sL useproxy.dev/install | sh
```

ChatGPT, Claude web and Claude Desktop: add a custom connector with the URL `https://mcp.useproxy.dev/mcp`, or use the guided page at [useproxy.dev/welcome](https://useproxy.dev/welcome).

## 2. Sign in

The first tool call opens a browser window. Sign in or create an account. There is nothing to paste back; the client stores the OAuth token.

## 3. Run a query

Ask in plain language. The assistant chains the tools for you.

```text
What video ads is Nike running on Meta right now? Transcribe the top three.
```

```text
Find competitors of cursor.com and compare their Google and LinkedIn ads.
```

:::tip
Start with a brand, not a keyword. Brand lookups (`get_meta_platform_id`, `get_google_platform_id`) return ranked candidates so the assistant can self-correct on ambiguous names.
:::

## What happens next

- Each ad-library or analysis call uses one credit. Free accounts get 20 per day. See [Credits and plans](/docs/credits).
- When the daily cap is hit the tool returns an upgrade link instead of failing silently.
- The assistant can render results as an inline carousel in clients that support MCP UI.

---

# Machine-readable resources
Source: https://useproxy.dev/docs/resources

## Discovery

| Resource | URL | Notes |
| --- | --- | --- |
| MCP endpoint | `https://mcp.useproxy.dev/mcp` | Streamable HTTP, OAuth 2.0 |
| MCP manifest | [/.well-known/mcp.json](https://useproxy.dev/.well-known/mcp.json) | Endpoint, transport, auth, per-client setup |
| llms.txt | [/llms.txt](https://useproxy.dev/llms.txt) | Tool list and usage guide for agents |
| Agent skill | [/SKILL.md](https://useproxy.dev/SKILL.md) | Ad research playbook |
| Agent skills index | [/.well-known/agent-skills/index.json](https://useproxy.dev/.well-known/agent-skills/index.json) | Skill discovery |

## Auth

| Resource | URL |
| --- | --- |
| Auth guide (markdown) | [/auth.md](https://useproxy.dev/auth.md) |
| Protected resource metadata | `https://mcp.useproxy.dev/.well-known/oauth-protected-resource/mcp` |
| Authorization server metadata | `https://mcp.useproxy.dev/.well-known/oauth-authorization-server` |

## Runtime

| Resource | URL |
| --- | --- |
| Health | `https://mcp.useproxy.dev/health` |
| Sandbox | `https://mcp.useproxy.dev/sandbox` |
| Install script | [/install](https://useproxy.dev/install) |

## Product

| Resource | URL |
| --- | --- |
| Pricing (markdown) | [/pricing.md](https://useproxy.dev/pricing.md) |
| Install guide (markdown) | [/welcome.md](https://useproxy.dev/welcome.md) |
| Sitemap | [/sitemap.xml](https://useproxy.dev/sitemap.xml) |

There is no OpenAPI spec because there is no REST API. The MCP `tools/list` response is the authoritative schema; `llms.txt` mirrors it in prose.

---

# Sandbox
Source: https://useproxy.dev/docs/sandbox

## Endpoint

```bash
curl https://mcp.useproxy.dev/sandbox
```

No token, no account, no rate limit concerns. It returns the shape of a `get_meta_ads` result with two fixture ads:

```json
{
  "mode": "sandbox",
  "tool": "get_meta_ads",
  "auth_required": false,
  "result": {
    "success": true,
    "brand": "Nike",
    "platform": "meta",
    "count": 2,
    "ads": [
      { "ad_id": "sandbox_001", "page_id": "15087023444", "media_type": "IMAGE", "status": "ACTIVE", "ad_url": "https://www.facebook.com/ads/library/?id=sandbox_001" }
    ]
  }
}
```

## What it is for

- Verifying the response shape before wiring up a client
- Automated readiness audits that cannot complete OAuth
- Demoing the tool output without spending credits

## Health

`GET https://mcp.useproxy.dev/health` reports status, protocol version, transport and free-tier details.

---

# Analysis tools
Source: https://useproxy.dev/docs/tools/analysis

## analyze_ad_image

| Parameter | Type | Notes |
| --- | --- | --- |
| `media_urls` | string or string[] | Any image URL from a platform tool |
| `brand_name`, `ad_id` | string | Optional context |
| `total_impressions` | int | Enables a performance hypothesis |

Returns the image as a vision content block so the assistant can describe layout, copy and visual hooks.

## analyze_ad_video

| Parameter | Type | Notes |
| --- | --- | --- |
| `ad_archive_id` + `page_id` | string | Stable Meta identifiers, preferred |
| `tiktok_id` | string | Stable TikTok identifier, preferred |
| `media_url` | string | Only for a URL returned in the last few minutes |

Transcribes the voiceover and describes the visual sequence with Gemini. Prefer stable IDs: signed Meta and TikTok URLs expire quickly and the server re-fetches a fresh one for you. One video per call.

## search_competitors

| Parameter | Type | Notes |
| --- | --- | --- |
| `domain` | string | Find similar companies to this site |
| `company_name` or `description` | string | Name or market description |

Domain input finds similar sites; name or description runs a semantic search. Returns candidate companies with domains, ready for the platform lookup tools.

## get_competitive_brief

| Parameter | Type | Notes |
| --- | --- | --- |
| `brands` | object[] | `{ name, is_own_brand, ads: [{ id, impressions, start_date, format, hook_type }] }` |

Turns already-pulled ad metadata into a structured brief: winners, formats, hook mix and scenarios. No upstream call. **Free.**

## get_credit_balance

No parameters. Returns remaining daily credits, plan, reset time and upgrade or billing links. **Free.** See [Credits and plans](/docs/credits).

---

# Google Ads Transparency Center tools
Source: https://useproxy.dev/docs/tools/google-ads

## get_google_platform_id

| Parameter | Type | Notes |
| --- | --- | --- |
| `brand_name` | string | e.g. "Nike" |

Returns two lists: `advertisers` (name, `advertiser_id`, region) and `websites` (domain). They can resolve to different accounts for the same brand, so the assistant is told to query both.

## get_google_ads

| Parameter | Type | Notes |
| --- | --- | --- |
| `domain` | string | Company-wide search, e.g. "nike.com" |
| `advertiser_id` | string | Specific account, e.g. "AR0161..." |
| `limit` | int | Default 100 |
| `topic` | string | Narrow by topic |
| `region` | string | Region code |

One of `domain` or `advertiser_id` is required. Each ad carries format, dates and an `ad_url` for the next tool. Impression data is not exposed at list level.

## get_google_ad_details

| Parameter | Type | Notes |
| --- | --- | --- |
| `ad_url` | string or string[] | From `get_google_ads`; lists fetch in parallel |

Returns text variations (headline, description, destination URL), regional targeting and impression ranges. Impression min and max can be null; that is a Transparency Center limitation. Image variations carry an `imageUrl` for [analyze_ad_image](/docs/tools/analysis#analyze_ad_image).

## Credits

One credit per call, one per URL in a batch.

---

# LinkedIn Ad Library tools
Source: https://useproxy.dev/docs/tools/linkedin-ads

## search_linkedin_ads

| Parameter | Type | Notes |
| --- | --- | --- |
| `company_name` | string | Advertiser name |
| `keyword` | string | Free text |
| `company_id` | string | LinkedIn company ID |
| `countries` | string | Comma-separated ISO codes |
| `start_date`, `end_date` | string | ISO dates |
| `pagination_token` | string | From the previous page |

At least one of `company_name`, `keyword` or `company_id` is required. Results include a `paginationToken`; pass it back to fetch the next page.

## get_linkedin_ad_details

| Parameter | Type | Notes |
| --- | --- | --- |
| `ad_id` | string | The `id` from a search result |

Returns creative content, `targeting`, `totalImpressions` and `impressionsByCountry`.

## Data quality

- `totalImpressions` is a string range like "5k-10k", and can be null for running ads
- `impressionsByCountry` values are percentage strings
- `targeting` and `headline` can be empty; LinkedIn does not always expose them
- Dates can be null for running ads; `adDuration` is the fallback signal

## Credits

One credit per call.

---

# Meta Ad Library tools
Source: https://useproxy.dev/docs/tools/meta-ads

## get_meta_platform_id

Search the Meta Ad Library for a brand and return ranked candidate pages.

| Parameter | Type | Notes |
| --- | --- | --- |
| `brand_names` | string or string[] | One brand or a batch |

Returns up to three candidates per brand, verified pages first, then by follower count. Each candidate carries `page_id`, `page_name`, `image_uri` and a `may_be_inactive` flag so the assistant can try the next one if a page returns no ads.

## get_meta_ads

Retrieve currently running ads for one or more Meta page IDs.

| Parameter | Type | Notes |
| --- | --- | --- |
| `platform_ids` | string or string[] | From `get_meta_platform_id` |
| `limit` | int | Default 100 |
| `country` | string | ISO country code |
| `active_only` | bool | Only ads still running |
| `sort_by` | string | `total_impressions` or `relevancy_monthly_grouped` |
| `status`, `media_type` | string | Case-insensitive filters |
| `start_date`, `end_date` | string | ISO dates |
| `min_duration_days` | int | Long-running ads only |
| `include_reach` | bool | Enrich with EU reach where available |
| `trim` | bool | Default true; false returns full metadata |

Each ad includes `ad_id`, `page_id`, body text, `media_type`, `media_url`, start and end dates, and an `ad_url` into the public library. For a transcript, pass the ad's `ad_id` as `ad_archive_id`, together with `page_id`, to [analyze_ad_video](/docs/tools/analysis#analyze_ad_video).

## search_meta_ads_by_keyword

Search across all advertisers without knowing the brand.

| Parameter | Type | Notes |
| --- | --- | --- |
| `query` | string | Keyword, phrase, handle, domain or hashtag |
| `limit` | int | Default 100 |
| `sort_by` | string | Same vocabulary as `get_meta_ads` |
| `country`, `status`, `media_type` | string | Filters |
| `start_date`, `end_date` | string | ISO dates |

:::tip
For creator partnership ads, search the brand handle, domain or a partner hashtag. Coverage is best-effort because Meta does not label paid partnerships in the library.
:::

## Credits

One credit per call. Batch calls cost one credit per item.

---

# TikTok ad library tools
Source: https://useproxy.dev/docs/tools/tiktok-ads

## search_tiktok_ads

| Parameter | Type | Notes |
| --- | --- | --- |
| `advertiser_name` | string | Exact match, case-sensitive |
| `cursor` | string | From the previous page |

:::note
`advertiser_name` must match the name registered with TikTok. "Anysphere" works; "Cursor" and "anysphere" return nothing. On zero results the assistant retries with the legal or parent company name.
:::

Covers EU-delivered ads only, but global brands advertising in the EU appear. Results carry first and last shown dates and a `has_more` cursor. Trust `has_more`, not `total`.

## get_tiktok_ad_details

| Parameter | Type | Notes |
| --- | --- | --- |
| `ad_id` | string or string[] | IDs from search, or library.tiktok.com URLs |

Returns body, `brand_name`, `video_url`, `cover`, `landing_page`, `country_code` and dates. `landing_page` is the most reliable brand signal. Signed media URLs expire in hours, so pass `tiktok_id` to [analyze_ad_video](/docs/tools/analysis#analyze_ad_video) instead of the URL.

## Credits

Search costs one credit per upstream page fetched, up to five per call (about 12 ads per page). Details cost one credit per ID.
