Skip to content

Ad verification for your own campaigns

Check that your geo-targeted ads and landing pages render, redirect and localize as planned, from the countries and on the device types you paid for.

Proxy URL, exit IP in United States

http://USERNAME-cc-US-session-a1b2c3d4-ttl-15:PASSWORD@mobile-us.netdash.io:4000

Mobile exit IPs in United States

Your clientGateway -us
Your clientGateway -us
Sticky session: requests from your client go through the -us gateway to one exit IP for 15 min, while that IP stays available.

Illustrative routes, not live traffic. Exits are available in most countries; the countries shown are examples.

  • Mobile and residential exits, one syntax
  • Country-level targeting
  • Sticky sessions for a full check

Ad verification proxies for geo-targeted campaigns

A campaign targeted at one country and one device type can’t be checked from your office network. A wrong language, a broken redirect or the wrong offer on a landing page often shows up only in the market and on the device the campaign targets. Ad verification proxies let you load your own ads and landing pages from an exit IP in that country, on a mobile or desktop client, and keep a record of what was served.

netdash gives you mobile and residential exits with one username and password. You name the campaign country in the username, and a sticky session holds one check, from the first redirect to the screenshot, on one exit IP.

Why you can’t check a country-targeted ad from the office

Ad delivery and landing pages vary by visitor country and device. Ad platforms choose what to serve from signals that include the visitor’s IP address, and landing pages often redirect or localize on the same signal. From your office you see your own market, on your own network.

To see an ad and its landing path the way your audience does, the check has to come from that country, on the right device class. Your ad platform’s preview shows the creative as configured; a check from the campaign’s market shows what the redirect chain and landing page return there. For your own site’s language and currency rules in general, see localization testing; for organic rankings by market, see SEO monitoring.

A verification pass, step by step

  1. Step 1: Export the campaign plan

    Landing URLs, the placements you own or manage, target countries and devices.

  2. Step 2: Open one session per check

    Exit country = campaign country. Mobile for mobile campaigns, Scale for desktop, sticky 15 so the redirect chain and landing page share one exit IP.

    Sticky sessions
  3. Step 3: Load, don’t click

    Open the landing URL or the page where your ad runs. Never click ads to test them.

  4. Step 4: Record the evidence

    Redirect chain, final URL, status, screenshot and the other fields in the table below.

  5. Step 5: Compare with the plan

    Language, currency, offer, final URL and status against what the campaign specifies.

  6. Step 6: Archive and report

    Store the evidence with its session details and send mismatches to the campaign owner.

What to record for each check

What to record for each check
AttributeWhy it matters
Campaign ID and expected targetingTies the check to the plan you compare it against
Exit country, plan and session IDShows where the check came from, so you can repeat it
UTC timestampDelivery changes over time; the time makes records comparable
Redirect chain with status codesFinds broken hops, the wrong country site and unexpected redirects
Final URLConfirms visitors land on the page the campaign specifies
HTTP status of the landing pageCatches errors that a screenshot alone can hide
Full-page screenshotShows what was rendered, for review by the campaign owner
Language, currency and offer shownThe localization details most often wrong in a single market

Device and country configuration

Mobile campaigns use the Mobile plan; desktop campaigns use a residential plan. The examples use Scale: every residential plan uses the same syntax, and you switch plans by changing the host and port. The proxy string format explains each part of the username.

Mobile campaign, United States

mobile-us.netdash.io:4000 · USERNAME-cc-US-session-{SID}-ttl-15

Puppeteer with a mobile device descriptor, so the page renders its mobile layout.

Desktop campaign, Germany

scale-eu.netdash.io:2000 · USERNAME-cc-DE-session-{SID}-ttl-15

Puppeteer or Playwright with a desktop viewport.

Session mode and TTL

Sticky, 15 minutes per check

Covers the redirect chain, landing page and screenshot on one exit IP while that IP stays available.

Session ID

First 8 hex characters of a hash of campaign ID, country and check time

Letters and digits only, no hyphens. A new ID starts a new session for the next check.

Credentials

Your proxy username and password from the dashboard

Not your sign-in password. One pair for every residential and mobile plan.

Volume

A small sample per campaign, country and device

A page load that shows an ad may register an impression, so check only as much as verification needs.

Proxy settings for one campaign check

Pick the campaign country and plan. Mobile is preselected with a 15-minute sticky session.

Your route

Through the AshburnFrankfurt gateway to an exit IP in Via Ashburn (-us)United StatesCanadaMexicoBrazilArgentinaChileVia Frankfurt (-eu)United KingdomGermanyFranceSouth AfricaIndiaJapan, rotatingsticky for 15 minsticky for 30 minsticky for 12 hsticky for 7 days, on the Mobile plan.

Proxy URL

http://USERNAME-cc-US-session-a1b2c3d4-ttl-15:PASSWORD@mobile-us.netdash.io:4000

Replace USERNAME and PASSWORD with the credentials from your dashboard.

Mobile, Americas gateway, exit IP in United States, sticky for 15 min.

curl --max-time 30 -x "http://USERNAME-cc-US-session-a1b2c3d4-ttl-15:PASSWORD@mobile-us.netdash.io:4000" \
  "https://api.ipify.org?format=json"
import requests

proxy = "http://USERNAME-cc-US-session-a1b2c3d4-ttl-15:PASSWORD@mobile-us.netdash.io:4000"
proxies = {"http": proxy, "https": proxy}  # set both, or HTTPS requests bypass the proxy

response = requests.get("https://api.ipify.org?format=json", proxies=proxies, timeout=30)
response.raise_for_status()
print(response.text)
import { ProxyAgent, fetch } from "undici";

const dispatcher = new ProxyAgent({
  uri: "http://mobile-us.netdash.io:4000",
  token: "Basic " + Buffer.from("USERNAME-cc-US-session-a1b2c3d4-ttl-15:PASSWORD").toString("base64"),
});

const res = await fetch("https://api.ipify.org?format=json", { dispatcher, signal: AbortSignal.timeout(30_000) });
console.log(await res.text());
import { chromium } from "playwright";

const browser = await chromium.launch({
  proxy: {
    server: "http://mobile-us.netdash.io:4000",
    username: "USERNAME-cc-US-session-a1b2c3d4-ttl-15",
    password: "PASSWORD",
  },
});
const page = await browser.newPage();
await page.goto("https://api.ipify.org?format=json");
console.log(await page.textContent("body"));
await browser.close();
{"ip":"203.0.113.10"}

Your output shows a different address in the country you chose.

Illustrative routes, not live traffic. Exits are available in most countries; the countries shown are examples. For exits in Oceania, ask support which gateway to use.All locations

Capture the redirect chain with Puppeteer

Chrome takes the gateway in --proxy-server; the username and password go to page.authenticate(). page.emulate() sets a mobile user agent and viewport before navigation, so the landing page renders its mobile layout.

redirectChain() returns the requests that were redirected before the final one, so the script appends the final request and records each URL with its status code. The screenshot and a JSON record go into evidence/, named by campaign, country and device.

  • Loads pages only: no clicks, and no reloads to generate views
  • For a desktop campaign, use scale-eu.netdash.io:2000 with -cc-DE and leave out emulate()
  • Syntax-checked. Setup details in the Puppeteer guide and the Playwright guide
import { createHash } from "node:crypto";
import { mkdir, writeFile } from "node:fs/promises";
import puppeteer, { KnownDevices } from "puppeteer";

const USER = process.env.NETDASH_USERNAME;
const PASS = process.env.NETDASH_PASSWORD;

// One check of your own campaign: one country, one device.
const check = {
  campaignId: "spring-sale-us-mobile",
  country: "US",
  landingUrl: "https://www.yourcompany.example/spring-sale?utm_campaign=spring-sale",
};
const capturedAt = new Date().toISOString();
const sid = createHash("sha256").update(`${check.campaignId}:${check.country}:${capturedAt}`).digest("hex").slice(0, 8);

// Chrome takes the gateway here; the username and password go to page.authenticate().
const browser = await puppeteer.launch({ args: ["--proxy-server=http://mobile-us.netdash.io:4000"] });
try {
  const page = await browser.newPage();
  await page.authenticate({ username: `${USER}-cc-${check.country}-session-${sid}-ttl-15`, password: PASS });
  await page.emulate(KnownDevices["iPhone 15"]); // mobile user agent and viewport, before navigating

  const response = await page.goto(check.landingUrl, { waitUntil: "networkidle2", timeout: 60_000 });
  if (!response) throw new Error("No response for the landing URL");
  const chain = [...response.request().redirectChain(), response.request()].map((req) => ({
    url: req.url(),
    status: req.response()?.status() ?? null,
  }));

  await mkdir("evidence", { recursive: true });
  const base = `evidence/${check.campaignId}-${check.country}-mobile`;
  await page.screenshot({ path: `${base}.png`, fullPage: true });
  const record = {
    campaignId: check.campaignId,
    exitCountry: check.country,
    plan: "mobile",
    session: sid,
    capturedAt,
    redirectChain: chain,
    finalUrl: page.url(),
    landingStatus: response.status(),
    pageLang: await page.evaluate(() => document.documentElement.lang),
  };
  await writeFile(`${base}.json`, JSON.stringify(record, null, 2));
} finally {
  await browser.close();
}
Puppeteer

Which product matches the campaign

  • Mobile proxies

    Self-serve

    Mobile campaigns: check placements and landing pages from mobile exit IPs. Carrier, city and network generation can’t be selected.

    From $3.50/GB, graduated per order

  • Residential proxies

    Self-serve

    Desktop campaigns, with the same credentials and username syntax. The examples use the Scale plan.

    From $1.20/GB, graduated per order

Your campaigns only

Verify only campaigns you own or are authorized to verify, for example as the agency running them. Loading a page that shows an ad may register an impression, so keep samples small and use your ad platform’s own preview and verification tools where they exist. Never click ads to test them: our Terms of Service (§2) list click fraud and "any automated activity designed to mislead or defraud advertising systems" among prohibited uses. See how we expect netdash to be used.

Ad verification questions

Your own campaigns, or campaigns you’re authorized to verify, such as an agency checking the campaigns it runs for clients.

Loading a page that shows an ad may count as an impression. Keep samples small, never click ads, and use your ad platform’s preview tools where they exist.

No. Targeting is country-level, and the Mobile plan doesn’t let you pick a carrier or network generation.

Mobile for mobile campaigns, residential for desktop. Credentials and username syntax are the same; you switch by changing the host and port.

Long enough for one check. The 15-minute preset covers the redirect chain, landing page and screenshot on one exit IP. Use a new session ID for the next check.

Verify your next campaign

Start with one campaign, one country and one device, and compare the evidence record with the campaign plan before launch.

Privacy choices

We use cookies and similar technologies that this site needs to work and to remember your choice. We also use Google Analytics to understand which pages and features people use: in the EEA, the UK and Switzerland only with your consent. Live chat loads only if you open it. You can change your choice at any time under “Privacy choices” in the footer. Privacy Policy

Privacy choices

Choose what netdash.io may use. You can change this at any time under “Privacy choices” in the footer.

Necessary (always on)

Keeps the site working and secure, and remembers your privacy choices (nd_consent, 12 months).

In the EEA, the UK and Switzerland it stays off until you switch it on; elsewhere it is on unless you switch it off here. Google Analytics 4 measures page views, clicks on links and buttons, use of the price calculator, connection builder and code examples, scroll depth, file downloads, and page-performance metrics. It sets the cookies _ga and _ga_96MPNM6GHH, which last up to 12 months. Google processes this data, which may involve transfer to the United States. We do not send your name, email address or account details to Google Analytics. With this switched on we also remember a referral code or campaign you arrived with (nd_attr, 30 days), so a partner can be credited if you sign up.

Support chat (loads only when you open it)

Our live chat is provided by LiveChat. It loads only when you open the chat window. LiveChat then sets its own cookies and processes the messages you send and technical data about your browser.