See which ad people in each market are actually served
And keep proof of where the click leads. A campaign approved for Spain should show the Spanish ad and send the click to the approved Spanish page. Ludax lets you load that page from inside Spain, so you can see what a visitor there really got — and record it.
Buy the smallest amount of traffic, audit one campaign, then schedule the rest. Plans are valid for 30 days from activation.
- 137 COUNTRIES
- CITY TARGETING
- ONE VISITOR HELD 1–1000 MIN
- 127 BROWSER PROFILES
- METERED TO THE KB
Sample check — what a visitor in this market was served. Pick a market and device, then select any ad on the page to see what was recorded about it.
WHERE THE CLICK ENDED · EVERY STEP, SAME VISITOR
Illustrative sample data. Every slot, creative name, hash and figure on this page is an example of what a rendered check can return — not a measured result, a real campaign, or a delivery promise.
Load the page from the country or city you are checking — Madrid, not your office.
See the ad that actually appears in each slot, on mobile or desktop.
Keep it as proof: the ad, the click path, and the page the click ended on.
WHAT LUDAX DOES AND DOES NOT DO
- Ludax provides the home-internet connection in the market you choose, the country or city targeting, and a network path that stays the same visitor for the whole check.
- You provide the browser or verification tool that takes the screenshots, compares the ads and writes the report.
- Ludax is not an ad-reporting dashboard or a screenshot service.
Follow the evidence chain
Proof is a record you can hand to someone else: here is the page a visitor in that market opened, here is the ad they got, and here is where the click took them. A screenshot on its own proves very little. What holds up in a dispute is an unbroken chain: the page a visitor in that market loaded, the creative that rendered in the slot, the click URL behind it, every redirect hop, and the page the click finally landed on — all captured through one address that never changed.
The exit is the internet address the check appears to come from; holding one for the whole check is what “sticky session” means. If the exit rotates between two links in this chain, a geo mismatch can no longer be attributed to anything: the impression and the landing page were observed by two different visitors. One session per audit, retried on a fresh token rather than reused.
Campaign audit matrix
One campaign, six placements, five markets. Delivery is decided per impression, so the same line item can be compliant in one country and wrong in the next. Select any cell to open its evidence record.
Cells summarise five samples. A single deviating load is recorded but not raised; a status only turns red once it repeats across runs on the same market and device profile.
What belongs in the evidence bundle
A finding is only as good as the record behind it. This is the case file we would keep for one flagged placement — every row captured in the same session, on the same exit, in the same minute.
01Timestamp2026-04-18T09:14:22Z
Recorded in UTC at request time, not at write time. Store the publisher's local time too — dayparting explains a large share of "the creative was missing" reports.
captured_at 2026-04-18T09:14:22Z local_time 2026-04-18 11:14 CEST
02Exit country and cityes · madrid · AS3352
The exit's own reported geography, pulled in the same session as the capture. Without it the row is an unattributed screenshot.
-country-es-city-madrid
whoami {"country":"ES","city":"Madrid","asn":3352}03Device and TLS profilemobile web · chrome145
Slot inventory differs by form factor, so the profile is part of the evidence. Keep the pinned handshake matched to the user agent you sent — a mismatch is the most common reason a rendered load looks nothing like a real visit.
user_agent Mozilla/5.0 (Linux; Android 14) Chrome/145.0
04Rendered screenshotfull page + slot crop
Two images per slot: the whole page for context and adjacency, and a crop of the placement bounding box. Captured by your own tooling — LUDAX supplies the network path, not the capture.
page.png 1080×5240 slot-f1.png 320×50 @ y=4980
05Creative asset hashsha256 3f9c…a17b
Hash the asset bytes that rendered, then compare against the approved set. A hash that is not on the list is either a rotation you did not expect or a line item running where it should not.
asset cdn.example-dsp.com/c/8841/320x50.jpg sha256 3f9c81d0e6b4f27c95a3d8ee01c74b6ba9d2f5c81e330947bc21ff54ae83a17b approved_set no match
06DOM / HTML capturepost-render, 412 KB
Store the serialised DOM after JavaScript ran, not the raw HTML response. The raw document usually contains no ad markup at all, which is how HTML-only checks end up reporting an empty page.
dom.html 412 KB (post-render) raw.html 88 KB (0 ad nodes)
07Click URLadserver.example-dsp.com/click?cid=8841
The href as it appeared in the rendered creative, with its macros resolved. Requested on the same exit as the impression — a click from a different address is a different observation.
click_url https://adserver.example-dsp.com/click?cid=8841&geo=es
08Every redirect hop3 hops · 302 · 302 · 200
Chains branch on geography, so the hop that matters often only appears from inside the market. Keep the status code, the location header and the timing of each hop, in order.
1 302 adserver.example-dsp.com/click?cid=8841 2 302 track.example-affiliate.net/r/es 3 200 brand.example.com/es/oferta
09Landing page result200 · pt-BR page
The final document, its declared locale, its currency and whether the jurisdiction's legal line is present. This is where localised campaigns fail most quietly.
status 200 html_lang pt-BR (expected es-ES) currency BRL (expected EUR) disclaimer missing
CONTACT SHEET · 4 OF 5 SAMPLES
Drop your own captures in here: the bundle is only persuasive when the same placement was sampled several times and one sample is visibly different from the rest.
- Gateway
gw.ludaxproxy.com:9999(Residential TLS · HTTP and HTTPS)- Capture
- Yours. LUDAX provides the network path and the geography; screenshots, hashing and diffing stay in your tooling.
From approved brief to observed delivery
The audit is a comparison, not a report. On the left, what the campaign was approved to do. On the right, what a visitor in Madrid was actually served on 18 April. Five dimensions, one scene.
ES only, Madrid metro weighted
exit es/madrid · AS12345 · 5 of 5 samples in-market
Country and city both resolved as bought. Nothing to raise.
2 assets approved · sha256 8ad1…, c04e…
sha256 3f9c…a17b — not in the approved set
One of five samples rendered an asset that is not on the approved list. Repeated on the 09:14Z run — worth raising with the DSP.
es-ES copy · EUR pricing · ES disclaimer required
creative en-US · landing html_lang pt-BR · currency BRL · disclaimer missing
Untranslated assets shipped live and the click resolves to the Brazilian page. The missing jurisdiction disclaimer is the part with legal exposure.
inclusion list, 12 domains, news and sport
unit seen on 9 of 12 · 0 off-list domains · adjacency captured
Three domains did not serve the unit during the window — absence in one run is not evidence a placement stopped running.
brand.example.com/es/* only
302 → track.example-affiliate.net/r/es → 200 brand.example.com/es/oferta
An affiliate hop was added in the middle of the chain. The final host is in scope, so this is a note rather than a breach — but it only appears from inside ES.
Sample data. Both sides of this comparison come from your own systems: LUDAX only guarantees that the observed side was collected from the market and device profile you asked for.
Read this before you schedule a run
No artificial impressions or clicks. Ever.
Verification loads exist to be read, not to be counted. Do not generate impressions or clicks for effect — not on your own campaigns, and never on anyone else's. Click fraud, inflating engagement signals and depleting a competitor's budget all breach the acceptable use policy, and accounts are terminated for it.
Verification also means observing public delivery only: pages any visitor in that market can load. Not advertiser dashboards, not publisher back-ends, not reporting APIs you have no credentials for, and nothing behind an access control.
Treat impressions as probabilistic
A creative not appearing in one check is not proof of absence, and one appearance is not proof of a pattern. Auctions, frequency caps, budget pacing and daypart all change what fills a slot minute to minute.
DO sample each placement repeatedly per market and device · keep every raw response · only call it a finding when it repeats
Render in a real browser
Most placements only resolve after JavaScript runs, so an HTML-only fetch reports a page with no ads on it. Answer consent dialogues where they gate ad markup, and match the pinned TLS profile to the user agent you send.
DO one sticky session per browser context · SO the exit cannot change mid-load
Budget for media bandwidth
A rendered page with autoplay video can be several megabytes, and traffic is metered to the kilobyte including discarded loads. Block video and heavy images when you only need to know which advertiser filled the slot; load media in full only when the creative asset itself is the evidence.
DO size the month with the estimator above before you schedule a run
Hold the session across the whole chain
Impression, click, redirect hops, landing page. If the exit rotates between steps the trail stops being coherent and a geo mismatch cannot be attributed to anything. Two to five minutes covers a rendered load and its landing page.
DO -session-adv31-time-5 · retry on a fresh token rather than reusing a failed one
import requests
USER, PASS = "YOUR_USERNAME", "YOUR_PASSWORD"
def proxy(country, city=None, session=None, profile="chrome145"):
pw = f"{PASS}-country-{country}"
if city: pw += f"-city-{city}"
if session: pw += f"-session-{session}-time-5"
pw += f"-profile-{profile}"
url = f"http://{USER}:{pw}@gw.ludaxproxy.com:9999"
return {"http": url, "https": url}
# one sticky exit for the impression, the click and the landing page
p = proxy("es", city="madrid", session="adv31")
page = requests.get("https://example-publisher.com/article", proxies=p, timeout=30)
# follow the click on the SAME exit and keep every hop
click = requests.get("https://adserver.example-dsp.com/click?cid=8841",
proxies=p, timeout=30, allow_redirects=True)
hops = [(r.status_code, r.headers.get("location")) for r in click.history]
# store the exit region with the evidence, or the row proves nothing
region = requests.get("https://api.ludaxproxy.com/whoami", proxies=p, timeout=15).json()Full parameter reference in the documentation.
Ad verification FAQ
01How many checks do I need before I trust a result?
Ad delivery is decided per impression, so one load proves nothing. Sample a placement several times per market and per device before you record a creative as absent — and store every raw response so the sample can be re-read later.
02Can I verify mobile placements?
Mobile-web placements, yes: drive a mobile-profile browser through a residential exit and pin the TLS profile to the user agent you send. In-app inventory is outside what an HTTP proxy can observe.
03How long should a session last?
Long enough to cover the impression, the click and the landing page — typically two to five minutes. If the exit rotates mid-chain the redirect trail stops being coherent evidence.
04Do you provide screenshots or reports?
No. LUDAX supplies the network path and the geography; capture, diffing and reporting stay in your own tooling.
05Residential TLS or standard Residential?
Residential TLS is the product priced on this page: $1.49 for 1 GB, down to $0.74 per GB at 1 TB. Standard Residential is a separate product from $0.49 per GB, without pinned browser handshakes. Neither can promise a challenge-free rendered load.
Audit one market. Then all of them.
Buy the smallest amount of traffic, load one campaign's placements from inside the market you bought, and compare what rendered with what was approved.
$1.49/ 1 GB · $0.74 / GB at 1 TB