Skip to content

Documentation

How the instrument works.

AutomatedTraffic runs authorized, automated tests against hostnames your organization has verified. There are two kinds of unit: HTTP requests and automated browser sessions. Neither is a human visit, and no report presents them as one.

Getting started

  1. Create an account. Passwords need at least ten characters.
  2. Confirm your email with the link we send. Trial credits are granted once, on verification.
  3. Add and verify a domain under Domains.
  4. Create a campaign under Campaigns, review the estimate, confirm you are authorized to test the target, and launch.
  5. Follow progress live and read the report when it completes.

Domain verification

When you add a hostname we generate a one-time token. It is shown only once, because we store only its hash, so copy it before leaving the page. If you lose it, request a new challenge; that replaces the previous one. Either method works.

Option A · DNS TXT record

Name:   _traffic-verify.<host>
Type:   TXT
Value:  traffic-verify=<token>

# example
_traffic-verify.example.com.  300  IN  TXT  "traffic-verify=3fa9c1…"

DNS changes can take a few minutes to propagate. Then press Verify now.

Option B · HTTP file

https://<host>/.well-known/traffic-verify.txt

traffic-verify=<token>

The file must return HTTP 200 with the token line as its body. Redirects to other hosts are not followed. Enable allow subdomains when adding the domain if campaigns should also reach its subdomains. If verification fails, the dashboard shows the verifier's reason, such as a missing record or a content mismatch.

Campaign setup

The campaign wizard has five steps.

  1. Target: a verified domain and a URL on it.
  2. Test type: http_test, one credit per HTTP request, or browser_validation, ten credits per automated browser session.
  3. Profile: region and device profile. Only options available to your organization appear.
  4. Limits: maximum units, rate per second, duration and an optional start time. Browser campaigns also take pages per session (one to five), the analytics events you expect, an optional GA4 measurement ID, and whether analytics hits are intercepted (the default; never sent) or delivered (sent, for end-to-end tag testing; filter them from reporting).
  5. Review: the credits required and any warnings. You confirm that you own the site or are authorized to test it.

A campaign stops at whichever comes first: maximum units reached, duration elapsed, cancellation, or credits exhausted. It can be paused and resumed while queued or running.

Reading reports

Every report keeps three categories apart.

  • Automated test activity: HTTP requests and browser sessions attempted and completed, errors, billable units and credits consumed.
  • Analytics events observed: analytics calls detected during browser sessions, whether intercepted or delivered. They come from our automated sessions, not from people.
  • Verified human visits: always 0. The product does not generate, measure or sell human visits.

You will also find status and error distributions, latency percentiles (p50 to p99), a timeline, and for browser campaigns the average load time, console errors and any expected events that went missing. In flight after stop counts requests already sent when the campaign was paused or cancelled. Event logs export as CSV and reports download as JSON.

Data retention

Raw events, meaning every HTTP request, browser session and analytics event recorded for a campaign, are kept for 90 days after the campaign settles: it has ended and its credits have been charged and released. A retention job then deletes them and keeps a frozen copy of the report.

The frozen report still shows the summary, distributions, latency, timeline and browser results, and notes that raw events were removed. The event log and its CSV export are empty from then on, so download anything you need to keep before the 90 days run out. Ledger entries and payments are not affected.

GA4 validation

For browser campaigns, enter the measurement ID your pages should load, in the form G-XXXXXXX. This check needs no Google account. The report lists every measurement ID seen in the tag and collection requests of the automated sessions, and states whether yours was among them. With no ID entered, it lists what it saw and makes no comparison.

An owner or admin may connect Google Analytics under Settings, Integrations. Access is read-only, and disconnecting revokes the token at Google. After choosing a property, a campaign report offers a realtime check that reads the events the whole property received in the last 30 minutes. Only campaigns that deliver analytics hits can show up there; intercepted hits never reach Google.

Google may filter, sample or omit automated activity. A low or zero realtime count does not mean the tag failed, and a present event is not proof it came from this test. The events observed in the report are the primary evidence.

Credits and billing

When a campaign is created, including one scheduled to start later, max_units × credits_per_unit is reserved from your available balance. As each batch of work finishes, its billable units are consumed: one credit per HTTP request, ten per automated browser session. When the campaign ends, the remainder of the reservation is released back to available.

An HTTP request is billable when the target returned a response, whatever its status; a browser session is billable when its page navigation got a response. Timeouts, connection errors and blocked destinations are never billed.

Purchases, grants, refunds and adjustments change the available balance; reservations move credits from available to reserved; releases move them back; consumption removes them from reserved. Credits included in a plan are added to the balance each paid period and do not expire.

Owners, admins and billing members can cancel a subscription under Billing. The plan stays active until the end of the paid period and is then not renewed; the organization returns to the Free plan, and credits already in the balance stay there. Until the period ends, the cancellation can be undone with Keep subscription.

Teams and invitations

A person may belong to several organizations and switch between them from the sidebar. Every organization-scoped action uses the active one. Roles:

  • Owner: everything in the organization, including billing, its name, and appointing or removing other owners. The last owner can neither step down nor leave.
  • Admin: domains, campaigns, members and invitations, webhooks, integrations, billing and the audit log. Cannot appoint, demote or remove an owner.
  • Member: creates, runs, pauses and cancels campaigns against verified domains, and reads every report. Cannot change domains, the team, webhooks or billing.
  • Billing: plans, credit packs, payments and the credit ledger, and reads campaign reports. Cannot run campaigns or change domains or the team.

Owners and admins invite colleagues by email from Team, as an admin, member or billing member. The invitation link opens a page showing the organization and role; it is accepted by signing in with the invited address, or by creating an account with it, which then joins the organization directly. Invitations expire after seven days, and pending ones can be revoked from the same page.

Webhooks

Owners and admins can register public HTTPS endpoints under Settings, Webhooks and choose the events each one receives:

  • campaign.started, campaign.completed, campaign.failed and campaign.cancelled, as a campaign changes state;
  • billing.payment_succeeded, when a pack or plan payment is confirmed;
  • credits.low, when the available balance falls below the low-credit threshold.

Each delivery is a JSON POST of {id, type, created, data} with the headers X-AT-Event, X-AT-Delivery and X-AT-Signature. The signature is keyed with the endpoint secret (whsec_…), which is shown once, when the endpoint is created.

X-AT-Signature: t=<unix>,v1=<hex>

t    Unix time the attempt was signed
v1   hex HMAC-SHA256 of "<t>.<raw body>", keyed with the secret

Verifying a delivery

Compute the HMAC over the raw request body exactly as received, before parsing it, and compare in constant time. Rejecting old timestamps guards against replays.

import hashlib, hmac, time

def verify(secret: str, header: str, body: bytes, tolerance: int = 300) -> bool:
    parts = dict(item.split("=", 1) for item in header.split(",") if "=" in item)
    t, v1 = parts.get("t", ""), parts.get("v1", "")
    if not t.isdigit() or abs(time.time() - int(t)) > tolerance:
        return False
    expected = hmac.new(secret.encode(), f"{t}.".encode() + body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, v1)

A delivery succeeds when the endpoint answers with a 2xx status within ten seconds. Otherwise it is retried after 10 seconds, 1 minute, 5 minutes, 30 minutes and 2 hours, six attempts in all. Each attempt is signed afresh; X-AT-Delivery stays the same, so use it to ignore duplicates. An endpoint is disabled automatically after twenty consecutive failed attempts, retries included (a delivery that exhausts its retries counts as six); the reason is shown and it can be re-enabled. Send a test ping at any time, and read every attempt and its response status in the delivery log.

API tokens

Create tokens under Settings, API tokens, with scopes read, campaigns:write and domains:write and an expiry of 1 to 365 days. The token is shown once. Send it as a Bearer token; no CSRF header is needed.

curl https://<your-app-host>/api/v1/campaigns \
  -H "Authorization: Bearer ats_xxxxxxxxxxxxxxxx"

curl -X POST https://<your-app-host>/api/v1/campaigns/<id>/pause \
  -H "Authorization: Bearer ats_xxxxxxxxxxxxxxxx"

Errors always take the shape {"code", "message", "request_id", "details"}. Quote the request_id when contacting support. List endpoints paginate with ?cursor= and ?limit= (1 to 100) and return next_cursor.

Security model

  • Campaigns can only target verified hostnames, and their subdomains if allowed.
  • Target addresses are resolved and checked for every connection. Private, loopback, link-local and cloud metadata ranges are refused with UNSAFE_TARGET.
  • An operator-maintained denylist blocks sensitive third-party hosts.
  • Plan limits cap volume, rate, duration and concurrent campaigns.
  • Requests identify as automated. There is no CAPTCHA solving and no bot-detection bypass.
  • Sessions use HTTP-only cookies with CSRF protection. API tokens are stored hashed.

Found a vulnerability or abuse? Report it.

About this test traffic

Every worker of this service identifies itself. Requests whose user agent contains AutomatedTrafficTest/1.0 come from here. They are automated tests, not people, and no report counts them as human visits. HTTP requests, including the domain verifier's fetch of /.well-known/traffic-verify.txt, send it as the whole user agent; automated browser sessions add it to the end of Chromium's own, unmodified one.

# HTTP request
User-Agent: AutomatedTrafficTest/1.0 (+<site>/docs#test-traffic)

# automated browser session
User-Agent: Mozilla/5.0 (…) AutomatedTrafficTest/1.0 (+<site>/docs#test-traffic)

# <site> is the address of this service; the link leads to this section

Browser sessions run stock headless Chromium. Nothing hides that it is automated: navigator.webdriver is left true, and there is no fingerprint spoofing. The viewport and device profile are the ones the campaign chose.

  • Who asked for it. A campaign can target a hostname only after an organization has proved control of it, or of a parent domain that allows subdomains, with a DNS TXT record at _traffic-verify.<host> or a file at /.well-known/traffic-verify.txt. If either is present, someone able to change your DNS or web server placed it there. Removing it later does not by itself stop a campaign, so write to us as well.
  • How much. Every campaign has a fixed maximum number of HTTP requests or browser sessions, a rate and a duration of at most one hour, all within its plan's limits. Across every campaign and organization, no more than five requests or sessions start against one hostname in any second.
  • What it does not do. It does not solve CAPTCHAs or try to get past bot detection, and it never connects to private or internal network addresses. Analytics calls made during browser sessions are intercepted by default, so they do not reach your analytics provider, unless the organization chose to deliver them for tag testing.

Recognising, filtering or blocking it

  • Logs and CDN rules. Match the substring AutomatedTrafficTest/ in the user agent. It is present on every HTTP request and every request an automated browser session makes.
  • In the page. navigator.webdriver is true in every automated browser session, so a tag manager condition or a line of script can keep these sessions out of analytics, experiments or chat widgets.
  • Analytics. Hits are intercepted by default and never reach your provider. When an organization delivers them for tag testing, Google may filter some automatically; the checks above exclude the rest.
# nginx: refuse this service's requests
if ($http_user_agent ~ "AutomatedTrafficTest/") { return 403; }

// page script: skip analytics in automated sessions
const automated = navigator.webdriver || navigator.userAgent.includes("AutomatedTrafficTest/");

You may block the user agent at your firewall or CDN; the tests simply record the refusal. If you did not authorize this traffic, report it with the hostname and an approximate time; a log line helps. We can stop the campaigns concerned and, at your request, add the hostname to our denylist. A denylisted hostname cannot be registered by any organization, and our workers refuse to send traffic to it.