EchelonGraphBot: Radar scanning policy

If you have found EchelonGraphBot in your logs, this page is why, and How to opt out is how you make it stop. It is published by EchelonGraph, Inc., which operates EchelonGraph Radar and is the controller of any personal data Radar processes.

We are sorry if our probe has caused you trouble or noise. You do not have to justify a complaint to us, and you do not need our agreement to stop being probed. If the volume or the timing is the problem rather than the probing itself, tell us and we will change it — we would much rather adjust than be blocked, but the choice is yours, not ours.

Contact for everything on this page: [email protected].

Current status — 13 September 2026

Radar is probing third-party hosts. In the 24 hours to 13 September 2026 it contacted 2,446 hosts that are not ours — 2,446 distinct names, so one request each, and no host heard from us twice.

Corrected 9 September 2026. Until this date this box said “Probing of anybody but us is off” and “Radar took 40 domains … and is paused”. Both were false while they were published. Scheduled third-party probing was armed on 9 September 2026 and this page was not corrected with it, so for part of that day an operator who found EchelonGraphBot in their logs and came here to check was told we were not crawling anyone. That is the worst way this page can be wrong, because it invites you to conclude the request was not ours. It was ours.
What is true now, measured rather than intended. Over the 24 hours to 13 September 2026: 2,446 requests to hosts we do not own, across 2,446 distinct hosts — so the most any one of them heard from us is one request. 2,158 answered normally and 154 answered 403. Separately we contacted our own echelongraph.io 0 times in that window — self-probing last ran on 9 September 2026 (582 contacts that day) and has not run since, which is a change from what this page said on 9 September and is explained below.
The sample is no longer a sample. This page said probing ran over “one domain in every 200”. It now runs over every domain in our registry: the scheduler selects 9,619 of 9,999 active registry rows each day, the difference being the jurisdictions our sign-off record excludes. If you are in that registry you will be contacted once a day, not once every two hundred days — a stranger’s cadence — and not more often than that unless you are the domain’s operator and have asked us for more, which is described below.
What still keeps you out of it. The three controls named here before were about a mode that no longer applies, so they are replaced by the ones that actually bind now: your robots.txt is fetched before every hop and its refusal is final; a per-host budget of one request every five seconds and a floor of one probe per 24 hours for any host we do not own whose operator has not asked us for more are enforced in the prober before a request is made; and a registered opt-out removes you outright. The qualifier is load-bearing, a build guard exists to keep it here, and since 13 September 2026 it has two clauses. Our own hosts are deliberately probed far harder than that whenever self-probing is running — that is what the 582 contacts on 9 September 2026 were for, and a limit nobody has watched refuse anything is a limit nobody has tested. It is not running today, so that exercise is currently paused. And a domain whose operator has proved they control it and asked us to monitor it is checked no more than once every 30 seconds, never faster, and only while they are watching; how that works, how it stops, and how to see whether a domain is under it are under How often we re-probe you below. In the 24 hours to 9 September 2026 those controls refused far more than they allowed — of 20,170 jobs the prober took, only 7,301 became a request, with 10,187 refused by the rate budget and 2,558 refused by robots.txt.
Corrected 12 September 2026. Until this date this paragraph said a 403 from you “does not currently earn you a cooldown”, and that our backoff escalated on 429 and 5xx only. That stopped being true on 9 September 2026 and this sentence was left behind, so for three days this page told you a 403 bought you nothing while the prober was already backing off on it — and the backoff section four screens below said so. It does earn a cooldown: the wait starts at 1 minute, doubles on each consecutive failure, and is capped at 30 days, which is the same escalation described under the budgets above. The reliable way to stop us outright is still the opt-out below or a robots.txt rule, both of which we honour today.

What follows is the record of the first day, 7 September 2026, and it stands unchanged. That day Radar took 40 domains and probed 30 of them once each. It is kept here rather than folded into the numbers above because it is the day this page got its account of itself wrong three separate times, and the corrections are worth more to you than a tidy summary.
The other 10 of those 40 were refused at the robots.txt step, and we are going to be exact about what that did and did not put in anybody’s log, because we have now got this wrong three times in three different directions.
Nine of them we never reached at all. The connection failed before any HTTP request was sent — one refused at the TCP dial, two timed out, six failed at transport or TLS — and an unreadable robots.txt is a refusal, so nothing followed. Those nine may have no record of us at all, and we are not going to tell you what you will find.
One read a real robots.txt and it said no. That was sso.passport.yandex.ru, reached at the third hop of a redirect chain starting at yandex.ru. Three GETs were made and answered before we stopped, and each hop’s robots.txt is fetched before that hop’s GET, so the true number of requests we made across that chain is at least five and we cannot give you the exact figure. We do not record the intermediate hops individually, so we cannot tell you which two hosts those were. That is a gap in this very promise, and we have filed it against ourselves rather than leave you to find it.
Corrected three times, the last on 8 September 2026. This passage read “before any request reached the host itself”, false for the redirected one; then “those hosts will find our robots.txt fetch in their logs”, false for the nine we never reached; and it put the chain at “three requests”, which counted only the GETs.
Those 30 measurements are kept, not discarded. They are published to our internal results stream and written to our analytics store, under the retention periods stated further down this page. The public feed at /radar shows the trailing 24 hours, so those first-day rows are held and not shown — but “not published” is not the same as “not kept”, and this box said the second thing until 7 September 2026. (Corrected 13 September 2026: this read “There is still no public feed, so nothing about them is visible to anyone outside EchelonGraph”, which stopped being true when the feed began publishing — see the status table.) It read: “Radar is not probing anyone but us … probe results go to a log and to a sink that discards them.” Both halves were true when written and neither was true once probing ran.
We paused because our own legal sign-off record requires six controls to be recorded as verified running before a first third-party probe, and none of the six had been filled in. That is a record-keeping failure on our side, not something that went wrong for anyone we contacted.

Before scheduled probing resumes, all of the following will be true. This list was written to be satisfied before a first third-party probe, and on 7 September 2026 it was not; it now governs the resumption. Items already delivered are marked Done with the date; the rest are stated in the future tense because they are not done yet, and this page will change tense as each one lands:

  • Done, 7 September 2026. The maximum re-probe frequency and the retention periods are published below as numbers: once per host per 24 hours for any host we do not own whose operator has not asked us for more, observations kept 90 days, hourly and daily aggregates kept 13 months. Amended 13 September 2026 (#1834): the cadence gained a second exception, for a domain whose operator proved control by DNS and asked to be monitored — no more than once every 30 seconds, stated under How often we re-probe you.
  • Done, 6 September 2026. The robots.txt evaluator is wired to the probe path: a Disallow covering the path we would probe stops the probe, on hop 0 and on every redirect hop.
  • Done, 7 September 2026. The per-host and per-provider rate budgets and the backoff bounds are published below as numbers: one request per host per 5 seconds with a burst of 4 and one connection; 5 per second, burst 20 and 10 connections per provider; backoff from one minute, doubling, capped at 30 days — raised from 24 hours on 9 September 2026, when it was found that 24 hours could never exceed the once-per-24-hours re-probe interval that applies to any host we do not own whose operator has not asked us for more, and so never delayed anything.
  • Done, 6 September 2026. Every Radar request leaves our network from 34.72.193.151/32 — one address, not a range. It is a static, manually allocated NAT address, so you can allowlist it, rate-limit it or block it without asking us, and we will not change it without saying so here.
    Two limits, because they matter more than the number. First, the reverse DNS forward-confirms but it is Google’s generic name, not ours — 151.193.72.34.bc.googleusercontent.com resolves back to the address, so the check passes, but it identifies a Google Cloud customer rather than EchelonGraph. A cloud NAT address cannot carry a custom reverse name, so making it say echelongraph.io needs a different egress design, and that is not built. Second, and this matters if you are about to block it: this is our whole estate’s egress address, not Radar’s own. Radar probes leave from this address — 2,446 of them in the 24 hours to 13 September 2026, to 2,446 distinct hosts, one request each — and so does the rest of our estate, including transactional email. It is one address for both, which is a real limitation and not a detail: if you block it, you block more than a scanner, and you will stop mail you may want. Giving Radar its own address with its own reverse name is the fix, and it is not built. We would rather tell you that than let you find out. If you saw traffic from this address before 7 September 2026 it was ours and it was not Radar. If you see traffic from it you believe is not ours at all, tell us at [email protected] and we will check our egress records and say plainly which it was.
  • Done, 5 September 2026. The prober runs with its signing key mounted, so every Radar request already carries the signed receipt described under How to verify it was us. That receipt is checked by our verifier, not by you offline; the limit is stated there too.
  • • We will be able to mark a disputed observation as disputed, before the feed carries its first observation.
  • Done: the register 5 September 2026, the prober’s check of it 7 September 2026. The opt-out register is live — self-service and DNS-verified — and since the scheduled path was built the prober checks it before every request it makes. This line deliberately gives no grade — the badges beside each opt-out heading below, and the status table at the foot of the page, do that and are the ones to read. Corrected 8 September 2026, four times: this bullet has said opt-out was coming, that it was live at both tiers, that neither tier was live, and then that the status table was “the only place we grade it” — which was itself false, since opt-out carries badges in §6 as well. Every version that restated a grade drifted from it, so this one states a fact and points at the grades instead.

If EchelonGraphBot has appeared in your logs today, we want to know: email [email protected] with the source IP and the timestamp. It is either a defect on our side or someone using our name, and we will tell you which.

Throughout this page, Live today marks what the shipped prober does now, Partly live marks a mechanism that exists but is not fully wired or parameterised, and Not yet marks what does not exist today — where it sits beside a rule, that rule is a commitment we bind ourselves to before we probe anyone but ourselves. A commitment stated as a present fact is the failure this page exists to avoid.

Who we are, and what Radar is

EchelonGraph, Inc. is a security company. Radar is our free, public internet-observability feed. It measures publicly reachable web endpoints — reachability, TLS configuration, HTTP response headers — and publishes what it measured, with the time it was measured. How EchelonGraph handles personal data generally is set out in our Privacy Policy.

Radar is free and public. No account, no payment, no login and no customer relationship is required to read it, to be in it, or to dispute it. The operator of a domain we have measured has exactly the same access to the record as anyone else, and the same right to correct it.

What Radar publishes is a measurement, not a verdict about your organisation. Where Radar puts a letter grade on something — its HTTP security-header grade — that grade is attached to a single URL, in the manner of Qualys SSL Labs' per-server assessment. It is not a company-level rating. We do not aggregate endpoints into one score for a named company, and we do not sell such a score. This distinction is deliberate and we consider ourselves bound by it.

Radar's foundational rule, enforced in the prober's code and not merely stated here: Radar makes its own requests as an ordinary anonymous public client and measures its own responses. It never observes anybody else's traffic.

Radar is active. The Discovery Radars covered on our Responsible Disclosure page start from data that is already public and are described there; Radar is different in kind — it makes its own HTTP and TLS requests to the endpoints it measures — so it has this policy of its own, and nothing on that page should be read as describing it.

How a domain comes to be probed, and how long the record lasts

A probe job reaches the prober from exactly three sources. The wire contract accepts no others — a job carrying anything else is rejected before it is dispatched.

SourceWhat it means
Scheduled passA tiered schedule over our own registry of domains.
On demandSomebody asked for this domain to be measured. Today that is only the domain’s own verified operator asking us to monitor it, described under How often we re-probe you; the search and “run this scan” route on the public site, by which a third party could cause your domain to be probed, without your involvement, is not built (#1257).
Certificate transparencyA certificate naming this domain was published to the public CT logs, and that is what surfaced the name to us.
  • We will tell you which of the three put your domain on the list. Ask at [email protected], naming the domain.
  • An on-demand request from a stranger will buy no privileges. It will be charged to the same politeness budgets and defeated by the same exclusions as any other job, so a stranger will not be able to use it to have you probed harder than the schedule would, or to reach a domain you have excluded. Stated in the future tense because the on-demand route for a visitor is not built (#1257). The one on-demand caller that exists since 13 September 2026 is a domain’s own verified operator asking us to monitor it — a shorter interval for that one domain, which nobody but its operator can start, and which still meets every budget and every exclusion; it is described in the next bullet. The scheduler and the exclusion check are both live: the scheduler run continuously, and the exclusion check was consulted on every one of the 2,446 jobs behind those requests.
  • How often we re-probe you, and how long we keep it. No host we do not own is probed more than once every 24 hours, unless its operator has proved they control it and asked us to check it more often. That is refused by the prober itself before a request is made, not merely scheduled that way. Throughout this page a stranger is a host we do not own whose operator has not asked us for anything, and the 24 hours is a stranger’s cadence. There are two exceptions, they are different in kind, and each is stated here so that you can check it. The first exception is our own hosts, and it is deliberate. We probe echelongraph.io as fast as our own per-host budget allows, because a limit that has never refused anything is a limit nobody has watched work, and everything below this line is a promise we would rather test against ourselves than against you. Live since 8 September 2026. This sentence stood in the future tense for part of that day, while the change was merged and the prober carrying it was not yet deployed; it moved to the present tense on the day that revision shipped, which is the order we said we would keep. The exception is a match against a fixed list of domains we own, on a label boundary — so a name that merely ends in ours is a stranger and gets the 24 hours. That list is shared/pkg/ourhosts, it has one entry, and adding to it is a commit that has to say why we own the host. For our own hosts the interval is not shortened: it does not apply at all, because for a host we own it is a promise to nobody.
    The second exception is yours to grant, and it shortens the interval rather than removing it. Added 13 September 2026 (#1834). The operator of a domain can prove they control it — the same mechanism the opt-out register uses, a TXT record at _echelongraph.<domain> carrying a token we issue — and ask us, on the monitor screen at echelongraph.io/radar/monitor, to check that domain continuously. A domain under that consent is checked no more than once every 30 seconds. Its operator picks a cadence from a closed set — 30 seconds, 1 minute, 5 minutes or 15 minutes — and nothing faster than 30 seconds can be chosen, so 30 seconds is the commitment and the rung is the operator’s choice. What the prober applies today is one minute to every consented domain, whichever rung was chosen: it does not yet read the chosen cadence, so a 30-second choice is honoured at a minute — never faster than the floor, so nothing on this page becomes false, but do not read the rung you chose as the cadence in force until this sentence says otherwise. Consent is not ownership, and the two are never merged: a consented domain still claims a per-host slot before every probe and is refused if it is asked too soon; it still meets your robots.txt, the per-host and per-provider budgets, the backoff and the opt-out register exactly as a stranger does; and it is refused by the approved-jurisdiction exclusion exactly as a stranger is. What changes is one interval and nothing else. The consent is matched on the exact name, so proving example.com monitors example.com and not www.example.com; and a domain that is also in our registry keeps its once-a-day scheduled visit as well, counted against the stranger budget as before.
    How much traffic that can ever be, and whose budget it comes from. At most 25 domains can be under consented monitoring at once, across everyone; the twenty-sixth is refused with a reason that names the cap, never queued. So the most consented checks can produce is 25 domains, twice a minute, all day — 72,000 requests a day — counted where each job is published and refused above that. That ceiling is separate from the daily ceiling our sign-off record sets for hosts that did not ask us to contact them: consented checks are counted on their own and never draw on the stranger budget, so nobody can use a monitor to spend the ceiling that protects you, and the stranger ceiling never describes a population that asked.
    How it stops, and how you can see whether a domain is under it. A monitor runs only while someone is watching it: the screen renews a lease every 30 seconds, a lease that goes 120 seconds without renewal lapses, and our scheduler consults the register every 15 seconds — so close the last screen and nothing further is scheduled within about two and a quarter minutes, with no account and no action on your part. The proof itself is trusted for 7 days and then must be renewed by the same DNS check; remove the record and it cannot be renewed. To end it at once, remove the record and POST https://app.echelongraph.io/api/v1/public/radar/monitor/stop with the domain; that goes through only once the record is confirmed gone, so nothing a stranger can do stops a monitor whose owner is still publishing consent for it. To see whether any domain is under consented monitoring, and at the cadence its operator chose, ask GET https://app.echelongraph.io/api/v1/public/radar/monitor/<domain>: it needs no account, answers 404 for a domain nobody has asked about, and for one that has says whether it is pending, active, unwatched, expired or stopped. If our checks are arriving faster than a stranger’s once a day and that answer is not active, that is a defect on our side and we want the report at [email protected].
    An individual observation is kept for 90 days; the hourly and daily summaries derived from it are kept for 13 months. Both are deletions the store performs, not a policy someone has to remember to apply. The summaries still name your domain — they aggregate over time, not over subjects, so they are not anonymous and we do not call them that. Radar is running scheduled probes today, so these are the bounds actually in force, not the bounds that would apply if it were; and the resting interval for a stranger is a deliberately conservative one — raising it is a change to this page first and the system second. Where each of these lives, so you need not take our word: the interval is claimed per host before a probe by radar-prober/internal/reprobe against the value in shared/pkg/politeness, or against the consented value in shared/pkg/radar for a domain whose operator asked; the cap, the ceiling, the floor and the lease are constants in that same file, and the register is core-backend/internal/radarmonitor; both retention periods are TTL clauses our analytics store applies, rendered from shared/pkg/chschema. A test fails our build if any figure on this page stops matching the code that enforces it.
  • How hard we push, per host and per provider. To any one host: one request every 5 seconds sustained, one connection open at a time, and a short burst of 4. To any one hosting provider — an autonomous system, not one of its customers: 5 requests per second sustained, 10 connections, burst 20. After a 403, a 429, a 451 or a 5xx we wait 1 minute, double that on each consecutive failure, and cap the wait at 30 days.
    Both halves of that sentence changed on 9 September 2026, and the old version was worse than it looked. It read “after a 429 or a 5xx… capped at 24 hours”. A 403 — which is what most of you actually return to a bot you do not recognise, and which 820 of you returned to us in one day against six 429s — was not on the list at all. Worse, it was treated as a successful answer, so it CLEARED whatever delay earlier refusals had earned: one 403 in the middle of a run of 429s collapsed the next wait from sixteen minutes back to one.
    And the cap could not bind. It was 24 hours, which is also the soonest we ever re-ask any host we do not own whose operator has not asked us for more, so the longest delay the backoff could impose was exactly the delay you already had. Our own counters say it plainly: across 20,170 jobs the backoff refused one. At 30 days it can. A host that keeps refusing gets roughly a dozen daily attempts, at a stranger’s cadence — enough that a transient rule or an outage is not read as a permanent no — and then the interval grows to 34 hours, 68 hours, 5.7 days, 11 days, 23 days, and a month from the seventeenth refusal.
    Your Retry-After is still capped at 24 hours and that did not move. The 30 days is how far OUR OWN judgement escalates after repeated refusals; the 24 hours is how long a SINGLE header from you may park us, because a host answering Retry-After: 999999999 has said something broken and we will not treat it as a permanent opt-out nobody reviewed. Two different numbers doing two different jobs.
    Some of these are borrowed and the rest are ours, and the difference matters if you are checking us. The sustained per-host rate and the one-connection cap match the two reference crawlers: Apache Nutch ships fetcher.server.delay at 5.0 seconds with one thread per queue, and Heritrix waits 5× the previous fetch, floored at 3 seconds. We sit at the slower end of that pair. The burst of 4 is our own choice, and neither crawler permits back-to-back requests at all. We allow it because one observation is a robots.txt fetch, the request itself, and its redirect chain — http → https → www is the common shape — so four lets a single visit finish without a five-second pause between its own steps. It is four steps of one visit, not four visits; anything longer runs at the sustained rate. The per-provider numbers have no precedent to cite — no reference crawler publishes a per-provider budget — so they are our judgement, and they are deliberately lower than scheduled probing will need, so turning it on means raising them. We would like to tell you that raising them requires changing a number on this page. It does not. An operator can raise them through our admin API at any time, up to a hard ceiling in the code, and this page would not change — which is the gap we describe next.
    Where each of these lives, so you need not take our word: all eight are constants in shared/pkg/politeness, enforced by radar-prober/internal/probelimit and radar-prober/internal/backoff before a request is made. A test fails our build if any of these figures stops matching the code that enforces it.
    An operator can change all eight at runtime, and all eight are checked — but only while a prober is running, and since 7 September 2026 one is kept running. When a prober reads a policy that makes any figure here weaker — a higher rate, a bigger burst, more connections, or a shorter backoff — it says so in its own logs, naming the figure, its new value and the published one, and an alert fires. It repeats that every five minutes for as long as the figure stays weaker.
    The honest limit, and what it is now: since 7 September 2026 this service keeps one instance alive continuously, so a change to any figure here is read on the loader’s own interval — it re-reads the policy every 30 seconds — rather than whenever something next happened to run. That is the bound, and it is not “instantly”: one loader interval after the write, on a running instance. Two things still limit it. It is one instance, and a deploy replaces it; a change made in that gap is read when the new instance boots, not before. And a kept-alive instance is a setting we asked for, not a measurement we have made: we measured the old arrangement and have not yet measured this one, so this paragraph carries no uptime figure until we have.
    Corrected 7 September 2026 — this paragraph previously read: “The honest limit, measured rather than estimated: this service has no minimum instance count, so it starts, works and is reclaimed. Over the 44 hours to 7 September 2026 it was running 11% of the time, with a median gap of about an hour between instances and a longest gap of 14 hours. A change made while nothing is running is not noticed until something runs. We are not going to describe that as ‘within minutes’. Keeping one instance alive continuously is what fixes it, and that arrives when scheduled probing does.” Every number in it was true of the 44 hours it measured, and it is kept here because it was. Its last sentence was a promise — that a kept-alive instance arrives when scheduled probing does — and both arrived on 7 September 2026, the warm instance first and probing a few hours after it — and probing was paused again the same day, while the instance stayed. We brought the instance forward on its own merits, because the loader and the alert above are worth nothing on a service that is asleep, and for a few hours that was the only thing that had changed.
    What we do not alert on, deliberately: a change that makes us more conservative than we published. That leaves everything on this page true, and a rule that paged on it would be switched off within a week — taking the useful half with it. The build test above is the other half: it catches this page and the code disagreeing, at the moment someone edits either.
  • If you block us and never contact us, nothing is removed. Tier 1 stops future probes reaching you; observations already published stay until they age out or are superseded. Removal of what is already published is Tier 2, it is free, and it does not require a reason.

What a probe consists of

Live today

One Radar probe is a single well-formed HTTP GET of the origin's root path, over http or https. No POST, no crafted paths, no parameter fuzzing, and no follow-up request probing what the first response revealed.

Because “how many times did you hit me” is the question you are most likely to be asking, here is the complete set of requests one probe can make of you, so that a count in your access log reconciles against this page:

  • The GET itself. One.
  • Redirects. Where your server redirects us, we follow the chain up to a cap of 10 hops. Each hop is a further GET, so a probe that is redirected repeatedly is up to eleven GETs of your pages — and more requests than that in total, because each hop’s robots.txt is fetched before that hop’s GET, and a robots.txt fetch will itself follow up to five redirects. We are not going to put a single number on the worst case, because the honest one depends on how your redirects are arranged and we do not record the hops (#1725). Corrected 8 September 2026: this read “up to eleven requests”, counting only the GETs — the same undercount this page corrected in its status box and left standing here.
  • robots.txt. The robots check is on the probe path (see Rate and politeness), so each host also receives one GET /robots.txt, cached rather than re-fetched for every probe. A host whose robots.txt we cannot read gets nothing further, because we treat an unreadable file as a refusal. Whether it received the fetch at all depends on why we could not read it: nine of the 40 jobs on 7 September 2026 ended at this step, and in all nine the connection failed before any HTTP request was sent, so those nine may have no record of us at all. Corrected 8 September 2026: this read “receives that request and nothing else”, which was the same false claim the status box above had already retracted, left standing here because that fix corrected one passage and announced the claim fixed.
  • Both schemes. A domain reachable on 80 and on 443 is two separate jobs, one per scheme, so the counts above can appear once for each.

That is the complete set. We make no request of you that is not in that list.

The request

GET / HTTP/1.1
User-Agent: EchelonGraphBot/1.0 (+https://echelongraph.io/bot)
From: [email protected]
Accept: */*
X-EchelonGraph-Verify: https://echelongraph.io/verify-scan?token=v1.<payload>.<signature>
X-EchelonGraph-Receipt: v1.<payload>.<signature>
Method and targetGET / — the job carries a domain and a scheme, never a path or a port.
Ports dialled80 and 443 only.
User-AgentEchelonGraphBot/1.0 (+https://echelongraph.io/bot) on every request.
From[email protected] on every request, the robots.txt fetch included.
Accept*/*
X-EchelonGraph-Verify and X-EchelonGraph-ReceiptLive today A signed receipt for this request — one HMAC-SHA256 token, sent once as a clickable verification URL and once bare. Present when our signing key is mounted in the prober; absent otherwise, with the headers above still sent. See How to verify it was us.
Cookies, Authorization, any credentialNever sent, in any form.
Accept-EncodingNot sent; compression is disabled so that we measure what the server actually put on the wire.
ProxiesNone — the measurement is ours or it is not made.

Bounds on a single probe: whole-probe timeout 20 s (hard ceiling 60 s); TCP connect timeout 5 s; TLS handshake timeout 5 s; redirect hop cap 10; one connection per hop, not reused.

Two limits on the response body — and the larger one costs you bandwidth

LimitWhat it is
Body retained for the detectors: 64 KiB (hard ceiling 1 MiB)Held in memory while the header and mixed-content detectors run, then discarded. It is never stored and never published.
Total read off the wire from one response: 4 MiB (hard ceiling 32 MiB)Where a body runs past the retained cap, we keep reading it — counting and discarding as we go — so that we can publish the response's true size instead of the size of our own cap. Nothing beyond the first limit is kept.

The second figure is what one probe can cost you in bandwidth. A response body larger than 64 KiB is drained up to 4 MiB by default. We publish that number rather than the flattering one: an operator who meters egress will see it, and would be right to distrust everything else on this page if it were not here.

What we read, and what we keep

We read the response status line, the response headers, the TLS handshake and certificate chain, the timings of each stage, the redirect chain, and a bounded prefix of the response body. We keep less than we read, by design:

  • The response body is not stored. It is read in memory so that the header and mixed-content detectors can run, and it is then discarded. The published record has no field that could carry it.
  • The redirect chain is not stored. Only the number of hops and the final URL are kept; we do not publish a list of a third party's URLs.
  • Certificate problems are recorded, not treated as failures. We complete the handshake with verification switched off and verify the chain ourselves afterwards, against public trust anchors, so that an expired or mismatched certificate is reported as a measurement rather than as a probe that failed.

Switching verification off in the handshake changes nothing about your configuration and nothing about your security. It does create one exposure, and it is an exposure to the accuracy of what we publish about you: a party able to intercept the connection between our vantage point and your server could present a certificate that is not yours, which we would accept, grade and attribute to your domain by name on the public feed. Two things limit it, and neither is complete. We never act on the certificate: no credential is sent over that connection and nothing is trusted on the strength of it. And where our own trust store is not usable, an adverse chain verdict is withheld rather than published, so our defect cannot be printed as your defect. What does not exist yet is corroboration of a certificate from a second vantage point before publication Not yet; until it does, Right of reply and correction is how such a record gets corrected.

How to verify it was us

Anyone can put our name in a User-Agent string. That is precisely why we do not ask you to take the User-Agent as proof, and why every request also carries a signed receipt. Traffic claiming to be EchelonGraphBot is not necessarily ours, and if you are seeing abusive traffic under our name we want to know ([email protected]) — it is our reputation being spent.

Three channels are described below. The first exists and is forgeable. The second exists and is not forgeable, but it depends on our signing key being mounted and on your logs recording full request headers, and it can only be checked by asking us. The third exists in part: one address is published and you can act on it today, and what is missing from it is the machine-readable ranges file and reverse DNS that names us. Corrected 8 September 2026: this read “The third does not exist yet”, which this page contradicted 85 lines further down and which steered you away from a check you can make without us. Where you have no receipt to check, we offer a direct answer instead. Email [email protected] with the source IP and the timestamp, and we will tell you from our own egress records whether that traffic was ours.

(a) The User-Agent and its +URL

Live today

EchelonGraphBot/1.0 (+https://echelongraph.io/bot) follows the convention RFC 9309 §2.2.1 states for crawlers: “The product token SHOULD be a substring of the identification string that the crawler sends … The identification string SHOULD describe the purpose of the crawler.” The +URL resolves to this page. From: [email protected] is a mailbox a human reads.

This channel is a courtesy, not evidence. It is trivially spoofable. Use it to find us in your logs, not to conclude anything.

(b) A signed request header, and a public verifier

Live today

Every Radar request carries a signed receipt, as two headers with one value. X-EchelonGraph-Verify is a clickable URL, https://echelongraph.io/verify-scan?token=v1.<payload>.<signature>, and X-EchelonGraph-Receipt is the bare token. The token is an HMAC-SHA256 signature, keyed by a secret that never leaves our servers, over the host the request was addressed to, the port, the name EchelonGraphBot and the time of issue. It signs the hostname, not the address it resolved to, because the headers are written before we dial; and each redirect hop is issued its own receipt for its own host, so a host we reach through your redirect holds a receipt naming itself, not you. A third party cannot mint one, and a copied one exposes itself: the host and time it names will not match the request it was copied onto.

To check a request you found in your logs:

  1. 1. Find the request in logs that record full request headers — your application, reverse proxy or WAF. A default access log records the User-Agent only, and the receipt is not in it.
  2. 2. Copy the X-EchelonGraph-Verify value and open it in a browser: it is a link to our verifier, and the receipt is checked on load. Or paste the X-EchelonGraph-Receipt token, or the whole URL, into the box at echelongraph.io/verify-scan.
  3. 3. The verifier answers valid or not, and for a valid receipt echoes the host and port signed (as example.com:443), the name EchelonGraphBot and the time of issue. Valid, and matching the host and time on your log line, was us. Valid but naming a different host or time is a receipt copied from a different request, and was not.

What this does not give you. The receipt can only be checked against our secret, so you cannot verify it offline: you ask our verifier and take its answer, which is a degree of trust in us that a signature under a published key would not require. And when we rotate the key, every receipt issued under the old one stops verifying, so a genuine request from before a rotation will be reported as not genuine after it. We say this plainly because a verification scheme that quietly requires trusting the issuer is the thing this page exists not to do.

When there is no receipt. The receipt is emitted only when our signing key is mounted in the prober's environment. Without it the two receipt headers are simply absent, the User-Agent and From are sent as before, and the probe still runs. So a request under our name with no receipt is either not ours or came from a revision running without the key. The prober records which state it started in, and [email protected] will tell you which of the two it was.

This is the same receipt and the same verifier our Discovery Radars and the on-request Surface Scanner already use. An earlier version of this page specified a Radar-only header under a different name. It never shipped: the verifier at echelongraph.io/verify-scan already existed and already validated this format, and a Radar-only header would have meant building a second one.

(c) Published source ranges and reverse DNS

Partly live

One address is published, a machine-readable ranges file is not. The address is in What we promise above — 34.72.193.151/32 — and you can act on it today. What is still missing is this: a file you can fetch and diff, and reverse DNS that names us. When those land: we will publish the IP ranges Radar probes from, on this page, in a machine-readable form, and we will update that file before an address is brought into use, never after. Every source address will have reverse DNS resolving into a domain we control, and will forward-confirm — which today’s address does not: its reverse name is Google’s, as said above. That is the gap this section is still open for. It will forward-confirm — resolve the PTR, then resolve that name back, and it must return the address you started from. This is the same reverse-DNS confirmation pattern the major search crawlers use, and the practice Censys states for its own scanners: “The IPs we use have identifying rDNS, WHOIS, and an HTTP site that indicates ownership, intent, and contact information.”

We do not probe from residential proxies, from consumer VPN exit nodes, or from addresses we have not published. If you see traffic under our name from an address that is not listed, it is either not ours or a defect on our side — either way, tell us at [email protected] and we will tell you which of the two it was. We do not offer the file as proof that traffic is ours, only as the set outside which it should not be.

What we never do

This section is the important one. Each line is a commitment, not an aspiration, and several are enforced by the prober's code rather than by anyone's memory.

We neverWhat that means concretely
Attempt authentication of any kindWe send no credentials, no cookies, no Authorization header, no API key, no token. A redirect whose Location carries userinfo is refused, so the client cannot be induced into emitting Authorization: Basic against its will.
Use, guess, brute-force or reuse credentialsWe hold no credentials for any third-party system and we do not create accounts.
Exploit anythingWe verify a condition; we never trigger it. If a response header, a status code or a certificate indicates a weakness, that is the observation. We do not send a payload to prove it is reachable, and we do not confirm exploitability. We send no malicious traffic.
Access non-public areasOnly ports 80 and 443, only the root path, only the public response. Loopback, private (RFC 1918), link-local, CGNAT, multicast, reserved, benchmark, documentation, NAT64/6to4/Teredo and IPv6 site-local addresses are refused before the dial — for the origin and for every redirect hop, so a redirect cannot walk us into an internal network.
Bypass a technical barrierA block is an answer. A WAF challenge, a 403, a network-level drop, a Disallow — each is recorded as what happened and is not worked around. We do not solve challenges, rotate User-Agents, or vary our fingerprint to look like a browser.
Send malformed trafficEvery request we make of you is a well-formed HTTP request — the GET, each redirect hop, the robots.txt fetch, and nothing else. No fragmentation tricks, no protocol abuse, no oversized or deliberately invalid input.
Intercept or passively capture anyone's traffic — everRadar is a party to every communication it measures. It makes its own request and reads its own response. There is no sniffing, no tap, no passive collection, no interception of communications between other people. This is a categorical rule, not a current configuration: a passive-capture capability would put Radar under an entirely different legal regime, and we have deliberately built it so that it cannot be turned on by configuration.
Rotate addresses to evade a blockIf you block our published ranges, we stay blocked. We do not move to unpublished infrastructure, and we do not treat a block as an obstacle to route around. Blocking us is a legitimate, permanent answer.
Enrich observations to natural personsWe publish measurements about domains and endpoints. We do not attach registrant names, staff names, email addresses or other personal data to a published observation; we do not build profiles of individuals; and we do not sell or share such data, because we do not assemble it. We consult RDAP for two purposes, and neither reads a registrant: verifying, by hand, that someone asking for an IP-range exclusion controls what they say they control, which does not feed the published feed; and asking a domain’s own registry what it already publishes about the name — expiry, registration date, registrar, DNSSEC and status codes — for the domain’s Radar page, which stores those fields and no registrant. Corrected 13 September 2026: this row said we consult RDAP/WHOIS “for exactly one purpose” and that the lookup “does not feed the published feed”, which stopped being true when the registry lookup landed on 12 September 2026 (#1818).

Two of these mirror commitments the incumbents already make in writing, and we quote them so that our posture is recognisable rather than novel. Censys: “We never attempt to exploit vulnerabilities, bypass authentication, or access devices behind NAT.” Rapid7 Sonar: “At no point does Sonar bypass any technical barriers or otherwise access non-public-facing computers.” The ZMap paper puts the norm in general terms: “scan practitioners should refrain from exploiting vulnerabilities or accessing protected resources.”

Rate and politeness

Partly live

On 7 September 2026 this section governed real requests to third parties for the first time, against 30 domains, once each. It has governed real third-party traffic continuously since 9 September 2026: 2,446 requests to 2,446 distinct hosts in the 24 hours to 13 September 2026. That first run took a hash sample rather than the registry: a fixed one-in-two-hundred slice, the same domains every cycle rather than a rotating one that would have reached everyone eventually. We started there on purpose, because these rules had never governed a request to somebody else. It no longer runs over a sample at all — since 9 September 2026 the scheduler selects every domain in our registry, 9,619 of 9,999 active rows a day, the difference being the excluded jurisdictions — at no more than one probe in 24 hours per host we do not own whose operator has not asked us for more. (Corrected 12 September 2026, #1806: this sentence read “Scheduled probing ran over one domain in every 200 in our registry”, and when the sampling constant was redefined on 9 September 2026 it was swapped into this past-tense sentence without rewriting it — so the page described the first run as covering every domain, in a sentence that then read “in our registry in our registry”, and still called it a fixed hash sample.) We stopped because our own sign-off record requires six controls to be recorded as verified running before a first third-party probe, and none of those six had been filled in. Nobody was harmed and nothing went wrong; the paperwork was simply not done, and doing it afterwards is not the same thing. What follows is the set of rules that bind us, stated so that they can be held against us; the status table at the foot of this page says, row by row, which of the mechanisms behind them exist today.

robots.txt — our HTTP compliance story

Partly live

Radar's HTTP fetches are bound by robots.txt, per RFC 9309. The evaluator is wired to the probe path: every probe consults robots.txt before hop 0 and before every redirect hop, and a disallowed path is refused rather than probed. This page promised that would happen before any host that is not ours is probed. It did, and on 7 September 2026 hosts that are not ours were probed under it — 40 jobs, 30 probed, 10 refused at this step. Concretely, the rules are:

  • • We fetch and cache robots.txt per host before probing it, and we match against our product token EchelonGraphBot and against *.
  • A Disallow covering the path we would probe means we do not probe it. There is no override, no allowlist of “important” hosts, and no exception for our own convenience.
  • • Non-200 responses follow RFC 9309 §2.3.1, in the direction that costs us rather than you: a 4xx means the file is unavailable and we may proceed (§2.3.1.3) — except a 403 and a 429, which we treat as a complete disallow; a 5xx or a network error means the file is undefined and we assume complete disallow (§2.3.1.4) — with one exception we would rather state than have you find. If we already hold that host's robots.txt from an earlier successful fetch, §2.4 lets us go on using it while it is fresh enough, and we do: up to 24 hours normally, and up to 8 days while the host stays unreachable. A host we have never successfully fetched has nothing to fall back to and is disallowed outright. A host that is failing is never a host we probe harder.
  • 429 and 403 are our two deliberate departures from the RFC's literal text. RFC 9309 would treat both as ordinary 4xx and let us proceed. We treat each as a complete disallow. A host that answers “too many requests” has told us something and we intend to hear it. And a 403 on robots.txt is, overwhelmingly, a firewall refusing a client it does not recognise — not a site declaring it has no rules. Reading it as permission would mean the host most determined to keep us out is the one we grant ourselves the widest licence over, which is the opposite of what this page is for. §2.3.1.3 grants a crawler a permission rather than imposing an obligation, so declining it in these two cases breaks no conformance claim we make.
  • Corrected 12 September 2026, and stated rather than done quietly. Until that date this page said “429 is our one deliberate departure” and that a 4xx let us proceed without qualification. Both were true until a 403 began denying. We measured the effect before making the change, on 150 of the domains in our registry: 75.3% answer 200, 10.7% answer 403 and 9.3% answer 404. So it reaches about one host in nine, and a 404 — which really does mean there is no file — keeps its allow-all.

RFC 9309 §1 is explicit that “These rules are not a form of access authorization.” We agree. We treat robots.txt as an instruction we follow, never as permission we have been granted.

The gap robots.txt does not cover — and what we do about it

robots.txt governs HTTP requests. It has no counterpart at the IP layer. The ZMap paper says so directly: “there is no IP-level equivalent of the HTTP robots exclusion standard.” Reading your robots.txt at all requires a DNS lookup, a TCP connect and — on 443 — a TLS handshake. So a host that disallows us still saw one connection from us, and that connection unavoidably reveals reachability and certificate facts. There is no standard by which you can forbid the connection itself. Our position, stated as a rule rather than left implicit:

  1. 1. Where robots.txt disallows the path we would probe, we do not probe it and we publish no observation for that host from that attempt. We do not launder the robots.txt fetch into a measurement.
  2. 2. Because the standard gives you no IP-level way to refuse the connection, we provide one ourselves. That is what How to opt out is. Blocking our published ranges, or a verified exclusion, are the IP-layer equivalents of a Disallow, and we treat them with the same finality.

Rate, budgets and backoff

Partly live

Politeness in Radar is enforced as cadence — how close together two requests may land — together with a cap on how many may be in flight at once, in shared state so that every prober instance charges the same budget for the same target.

ControlBehaviour
Per-host budgetA token bucket bounding how often probes to one host may start, plus a hard cap on how many probes may be in flight against that host at once. A slow host does not accumulate our connections.
Per-provider (per-ASN) budgetA separate budget charged in parallel, because a thousand distinct hostnames probed politely is still a thousand requests at one provider when a large CDN fronts them. A probe must fit inside every budget it is charged to, or it does not start.
Backoff on 429 and 5xxConsecutive failures are counted per host and produce an exponentially growing not-before instant. That state is shared across every prober instance, so our fleet learns from your 429 once rather than one instance at a time.
Retry-After is a floor, never a ceilingWe take the longer of your Retry-After and our own exponential backoff, capped at 30 days. RFC 9110 §10.2.3 tells us how long you want us to wait, and we do not read that as permission to return the moment the period elapses. Taking the longer of the two delays is our own choice, not something the RFC requires of us. A host on its fifth consecutive 429 that answers Retry-After: 1 is not probed every second.
Failure modeEvery one of these fails closed. If the shared state cannot be read, we do not know whether a host asked us to stop, so we do not probe. A politeness limiter that fails open is not a limiter.

The mechanisms above are implemented, their numbers are set, and since 7 September 2026 all eight are published on this page as figures. They are in What we publish about ourselves above: the rate, burst and in-flight cap per host, the same three per hosting provider, and the backoff base and its ceiling. Until that date this paragraph said they were not published, and said you were entitled to notice the difference — which you were. They are compiled into the prober, validated at boot, and refused if they fall outside the bounds the code enforces; the prober prints all eight on its boot line. The ninth — the minimum interval before any one host is probed again — is in force at 24 hours for every host we do not own whose operator has not asked us for more, and is enforced where it can refuse rather than where it can only schedule: for a stranger the prober claims a per-host slot before probing, so a second job for the same host inside that window is refused by the prober, not merely left unqueued by the scheduler. For a domain whose operator proved control and asked us to monitor it the same claim is made at the consented interval instead — one minute today, never under the published 30-second floor — and refused the same way (#1834; How often we re-probe you above). For a host we own there is no such claim and the per-host budget is the control instead, which is the whole reason we can tell you it works. The scheduler and the consumer are RUNNING, against echelongraph.io only.
Corrected 8 September 2026: this passage said the interval was “in force at 24 hours” without qualification, that “the prober claims a per-host slot before probing” with no exception, and that the scheduler and consumer were “built and switched off”. The first two contradicted this page’s own §1.1, and the third was false while the scheduler was completing a cycle every few seconds. It was found by a post-close audit and not by us: the sweep that corrected the sibling sentence elsewhere on this page searched only the passage already being edited.

We aim, in the words Qualys SSL Labs uses for its own assessments, to be “slow, non-intrusive, and [to] not consume significant resources.” If we are not achieving that against your infrastructure, that is a defect on our side and we want the report.

How to opt out

Partly live

Two tiers. The scheme follows Censys, whose opt-out is the reference implementation: the NDSS 2025 study Revealing the Black Box of Device Search Engine found that “Apart from Censys, none of the engines provide opt-out options, and most conceal their identity in the User-Agent.” That is a finding about the device search engines the study examined, not about scanners generally — other scanners plainly do operate opt-outs, and we quote two of them below.

The same study is worth citing against ourselves. Its Finding IV is that “Although Censys proposed the best practice of hosting a website on port 80 of each ScanIP to describe the scan's purpose and nature, no engines, including Censys itself, fully follow it in implementation.” That per-address ownership page is precisely what we commit to under Published source ranges above. We are holding ourselves to a standard that, on the published evidence, nobody currently meets — and, as at 13 September 2026, neither do we.

Tier 2 is real, takeable, and since 7 September 2026 it is on the path that stops a probe — but it has never had to stop one, and we are not going to call that proven. Scheduled probing is LIVE as at 13 September 2026, so an exclusion registered today has something to stop. As at 13 September 2026 you can register an exclusion, prove the domain by DNS, and see it recorded; the verified list is published every 60 seconds and our prober reads it every 30, so an exclusion is in the prober's hands within 90 seconds. What no exclusion has yet done is stop a real probe, because nobody has registered one. Its probe engine and its robots fetch each ask an opt-out gate before every request and every redirect hop — and since 7 September 2026 the list they are handed on the scheduled path IS the register, reloaded every 30 seconds and fail-closed until it loads. Corrected 7 September 2026: this paragraph previously said the gate was “a fixed allowlist of our own hostnames, not the register”. That was true of the operator one-shot tools, which still use that narrower allowlist, and it stopped being true of the scheduled path when that path was built — we left the older sentence in place, and it understated what registering an exclusion does for you. What is still unproven is the last step: no exclusion has ever stopped a real probe, because nobody has registered one. The mechanism is proven by its tests and by our own production logs; it is not yet proven by having refused somebody. Tier 1 is usable today — we publish one address and you can block it — but not in the form it describes, because the machine-readable ranges file does not exist and that one address carries our other services too. And removing observations we have already published is still a commitment rather than a mechanism: the public feed at /radar publishes observations, and nothing yet removes a domain from it. (Corrected 13 September 2026: this read “because there is no public feed to remove anything from”.) [email protected] is monitored today and a request reaches a human.

Tier 1 — self-service, immediate, no contact with us required

Partly live

Block our published source ranges at your edge. You do not need our permission, our agreement, or a reason we find satisfactory. We will not route around it.

You can do this today. The address is published: 34.72.193.151/32, above. What is missing as at 13 September 2026 is the machine-readable ranges file, which is a convenience rather than the mechanism. Block that address, or block the source addresses you have observed, and tell us at [email protected]; we will confirm which addresses are ours so that your block is complete rather than approximate. Read the caveat above before you do: that address carries our other services too, so blocking it stops more than Radar.

Here is what that does and does not achieve, stated as plainly as Censys states it — “Blocking connections from Censys' subnets prevents our scanners from indexing your services. However, this does not remove historical data from Censys datasets.”

Blocking our ranges
Stops future probes reaching youYes, immediately, and without any action by us.
Stops new measurements of the blocked hostsYes. A blocked probe produces no measurement of your configuration.
Publishes an “unreachable” record about you insteadNo, where we can tell. A refusal directed at us is not a fact about your availability, and we will not publish it as one: where we know a host is refusing us, we publish no unreachable observation for it. Be aware of the limit — at the point of measurement a network-level drop looks the same as an outage, so we cannot always tell the two apart. If an unreachable observation appears that you believe is your block, tell us at [email protected] and we will suppress it. That request needs no Tier 2 exclusion and we do not gate it on verification — suppressing an unreachable observation can only ever remove an adverse-looking record. Using Tier 1 must not cost you anything, or it is not a self-service right.
Removes observations we have already publishedNo. A self-service block is a network control; it is not a request to us, and we cannot act on a request we never received. Use Tier 2 for that.
Removes copies other people already tookNo. Nothing we do can recall a copy, cache or screenshot already held by a third party. No policy can honestly promise otherwise.

Tier 2 — verified exclusion

Partly live

For a domain this is self-service, and it does not require contacting us. Ask for the exclusion, publish one DNS record to prove you control the name, then tell us the record is there. No account, no reason, and no agreement from us:

POST https://app.echelongraph.io/api/v1/public/radar/opt-out
{"domain":"example.com","scope":"radar"}

→ publish  _echelongraph.example.com  TXT  "echelongraph-verify=<token>"

POST https://app.echelongraph.io/api/v1/public/radar/opt-out/verify
{"domain":"example.com","scope":"radar"}

Asking changes nothing on its own. Only the verified state excludes anything, and that is what the DNS record is for: an unverified exclusion list is a mechanism by which a stranger could remove your domain from a public record without your knowledge. Verification protects you, not us. scope is radar, surface-scanner or all, and defaults to all. Be aware of what that scope does and does not reach today: the register is read by Radar's prober and by nothing else — our Surface Scanner does not consult it — so a scope of all records your intention across our scanners and currently binds only the Radar side. We would rather you knew that than discover it. A verified domain covers every name beneath it, so proving example.com excludes api.example.com too — you do not have to enumerate your hostnames.

For an IP range, email [email protected] instead. The self-service register is by domain name and refuses an IP address outright, because an IP is not a name anyone can prove control of through DNS and we would rather refuse than half-honour it. For those we verify control from publicly verifiable records — RDAP/WHOIS — in the manner Rapid7 describes for Sonar: “we attempt to verify that the requestor has been delegated or otherwise controls the network addresses … typically … via WHOIS and other tools.” Censys states the same test: “We honor opt-out requests from operators who can verify network or domain ownership through public WHOIS data.”

Once verified, a Tier 2 exclusion:

  • Partly live is recorded, published to our prober within 90 seconds, and is the list the prober checks before every scheduled request. It stops no probe today only because nobody has registered an exclusion. Corrected 7 September 2026: this bullet read “not yet the list the prober checks before a request, so it stops no probe today. Nor does it need to: we probe only our own hostname”;
  • Not yet removes the excluded scope from the public Radar feed, including observations already published for it — a commitment, not yet a mechanism: the feed publishes, and nothing yet removes a domain from it (corrected 13 September 2026; this read “no feed exists to remove anything from”); and
  • Live today is honoured regardless of your reason. We do not require one.

It still cannot recall copies third parties already hold.

What is actually built, stated so you can hold us to it. The gate is written to fail closed: given no readable register it answers “unknown”, and the engine turns that into no request rather than into a probe — and after ten minutes without a readable copy that is its answer for every domain, so a register we cannot read stops probing rather than letting it through. Restored 7 September 2026: the paragraph below calls the ten minutes “the one that matters” and this page had stopped saying what it was. That property is real and tested, and it is why we were comfortable wiring it in its own change rather than shipping something permissive early. Two honest edges: a register of domain names has no opinion about a hop addressed to a bare IP address, so that one case is allowed through rather than refused; and the fail-closed behaviour, while it now governs every scheduled request, has never been observed refusing one, because no exclusion exists to refuse it. The 90 seconds is two scheduled steps — one to publish the register, one for the prober to read it — so it is what you should expect in normal operation, not a guarantee: a step that fails is not retried until its next turn, which adds another minute or another thirty seconds. The ten minutes does not stretch, and it is the one that matters, because it is the point at which we stop rather than carry on. But as at 13 September 2026 no verified exclusion is in force. That is measured, not assumed: the list our prober loads is built from exclusions that completed DNS verification, and on 8 September 2026 it held zero; re-read from the prober’s own load line on 13 September 2026, it still held zero. A request that has not completed verification is not on that list and excludes nothing. Corrected 8 September 2026: this said “nobody has asked”, which we cannot show — we can show that nobody has completed one. Radar now probes third parties, so there is something for an exclusion to bite on; there is simply no exclusion. So the mechanism is proven by its tests and by our own production logs, and not yet by having stopped a real probe of someone else's infrastructure. We would rather say that than let the word “enforced” do work it has not done.

We would rather adjust than exclude, and we will say so once. If the problem is our cadence, our timing window, a particular hostname, or the way something is worded rather than the probing itself, say so and we will change that instead. But we will not make an exclusion conditional on hearing us out first.

Exclusions expire, and are re-verified

A Tier 2 exclusion runs for 12 months. Before it lapses we contact the verified address to ask whether it should continue; if it should, we renew it. Two reasons, both of which are the incumbents' own: operators often change their mind once they know what we are — Censys reports that “many operators rescinded their request for opt-out after understanding our scan intent” and that “many initial emails are sent by automated processes” — and a stale exclusion list is its own problem, because network blocks and domains change hands; Rapid7 re-checks in order to “remove stale entries where the WHOIS record has changed”, and so do we.

That re-contact is not a running process yet, and we would rather say so than let you find out. Nothing expires today — an exclusion stays in force until you tell us otherwise, and there is no expiry field for anything to act on. The self-service register also records no contact details for you by design: only the domain, the scope and the proof you published. So for a DNS-verified exclusion there is currently no address for us to write to. Treat the twelve months as the point at which we owe you a question, not as a clock that can take your exclusion away.

Expiry is not a trick to resume probing. If we cannot reach you, or you do not reply, the exclusion stays in force — silence renews it. Only an affirmative “you can resume” from a verified contact lifts one.

Prior art — the wording we modelled this on

We did not invent this posture. Qualys SSL Labs has run public, named per-server assessments for over fifteen years, and its opt-out is the most gracious in the industry — unconditional, apologetic, and offering to adjust before it offers to exclude:

“We apologize for any inconvenience that our scans may be causing for you. If you have a problem with how we're scanning, please get in touch. We will be happy to adjust our scanning so that it does not bother you. If, on the other hand, you object to your public web servers being scanned, we will add you to our black list … and you will not be scanned again.” — Qualys SSL Labs

The one place we depart from SSL Labs is verification: their list is unverified, ours is. We think that is the right trade for a feed where an exclusion also removes published records, for the reason given above.

Right of reply and correction

Partly live

Radar's purpose is to publish measurements about named third parties, and some of them will sound adverse. That obliges us to be correctable.

How to dispute an observation. Email [email protected] with the domain, the observation and what you say is wrong with it. You do not need to be a customer; there is no charge; and there is no contract to sign. Every observation carries the timestamp at which it was measured, so a dispute can be about the measurement, the method, or the fact that the world has moved on since.

A disputed observation is marked as disputed while it is unresolved. Not yet That is a commitment, and it is not yet built: the public feed exists and publishes as at 13 September 2026, and the dispute machinery does not. (Corrected 13 September 2026: this read “neither the public feed nor the dispute machinery exists” and promised the marking “before the feed carries its first observation” — the feed carried observations before the marking existed, so that promise was not kept and is withdrawn rather than re-dated.)Disputes reach a human at [email protected] today; what does not exist yet is the marking itself, on a feed that is now live. We adopt the dispute principle of the US Chamber of Commerce Principles for Fair and Accurate Security Ratings: “Rated organizations shall have the right to challenge their rating and provide corrected or clarifying data. … Disputed ratings should be notated as such until resolved.” The marking will appear alongside the observation, where a reader sees it — not on a page an operator has to know to ask for.

We do not adopt the same code's confidentiality principle, and we would rather say so than quote the code selectively. That principle reads: “Rating companies should not publicize an individual organization's rating.” Its signatories acted on it, and Radar plainly does publish, against a named domain, in public. Our position is that the principle is addressed to a company-level rating, and that what Radar publishes is a per-endpoint measurement in the manner of Qualys SSL Labs' per-server assessment, not a rating of your organisation. That distinction is the entire basis on which we publish at all. It is a judgement call rather than settled ground, and we are aware that a reader may weigh it differently.

How we resolve one.

  1. 1. We re-measure. Most disputes are resolved by the current state of the endpoint, not by argument.
  2. 2. If the observation was wrong, we correct it and say so; corrections carry the date of the correction.
  3. 3. If we still believe the measurement is right, we tell you why, we show the method, and the dispute marking stays visible until the disagreement is resolved or the observation is superseded by a fresh measurement.
  4. 4. An exclusion request is always available and is never conditional on the outcome of a dispute.

What we publish and what we do not. We publish the measurement and its timestamp rather than a characterisation of your organisation, and we state the method. We do not publish a company-level score, and we do not comment publicly on an individual organisation's posture outside the feed itself.

Implementation status

This table exists because a policy that describes mechanisms which do not yet exist is worse than no policy. It is accurate as at 13 September 2026.

MechanismStatus
This page at echelongraph.io/botLive today You are reading it. The URL returned HTTP 404 when measured on 5 September 2026, before this page shipped.
User-Agent and From on every probe requestLive today In the prober.
From on the robots.txt fetchLive today Fixed. The probe, the robots.txt fetch and the redirect hops of both go through one identity stamp, and a test fails if a new outbound path skips it.
X-EchelonGraph-Verify signed receiptLive today In the prober, on every request and every hop, when our signing key is mounted; absent otherwise, with User-Agent and From still sent.
Public verifier for Radar requestsLive today /verify-scan accepts a Radar receipt — the same verifier the Discovery Radars and the Surface Scanner use. It checks against our secret, so it is an answer from us, not a check you can make alone.
Answering a “was this traffic yours?” enquiry from our own egress recordsLive today This is what we offer for a request that carries no receipt, and in place of the unpublished ranges. [email protected] is monitored and our egress addresses are known to us. No such enquiry has been answered yet.
Published source IP ranges, forward-confirmed rDNS, per-address ownership pagePartly live The address is published: 34.72.193.151/32, a single static NAT address, taken from our egress configuration on 6 September 2026. Radar probes left from here on 7 September 2026, and this address is the only egress our estate has, so they left from it — but that is still read from our egress configuration and not observed from the receiving end: no third party has shown us a log line with this address in it. Our other services use it too. Reverse DNS forward-confirms to Google’s generic name rather than ours, and a per-address ownership page is not built.
robots.txt handling (RFC 9309)Live today On the probe path. Every probe consults robots.txt before hop 0 and before every redirect hop, and a disallowed path is refused rather than probed. Exercised against a third party on 7 September 2026: a redirect chain reached sso.passport.yandex.ru, whose robots.txt returned Disallow: /, and the probe was refused at that hop rather than followed.
Per-host and per-ASN budgets; backoff; Retry-After as a floorPartly live In the binary, wired, and governed real third-party traffic on 7 September 2026, for the 30 probes that ran before probing was paused. Corrected 6 September 2026 — the previous row said “not in the binary”, which is no longer true: go list -deps ./cmd/prober now contains both the rate-limit and the backoff package, and the service builds the gate at boot with the numbers above. The operator one-shot still deliberately runs without budgets, since it makes one request to our own hosts. A per-host budget has now been observed refusing, for the first time: 164 refusals out of 178 jobs on 8 September 2026 (prober revision echelon-radar-prober-00066-zsg). Until that day no budget had ever refused anything, and this row said so.
Why it stays Partly live, and read this before the number: those refusals are against echelongraph.io, which is ours. The budget has been watched working; it has NOT been watched working on a stranger’s traffic, and one does not evidence the other. It governed 30 real third-party probes on 7 September 2026 and refused none of them.
That earlier zero was not an accident of volume, and more traffic would not have fixed it: the re-probe interval is claimed BEFORE the budgets are consulted and its refusal is final, so at one probe per host per day — a stranger’s cadence — a host contributes one request and a budget of four back-to-back plus one every five seconds is unreachable by construction — raising the volume raised the interval refusals instead. Changed 8 September 2026 so the interval does not apply to hosts we own at all, which leaves the budget as the control that has to answer. It answered.
Observation retention periodLive today Published and enforced, 7 September 2026. Observations kept 90 days; hourly and daily summaries kept 13 months. Both are TTL clauses the analytics store applies, so they run whether or not anything is probing.
Maximum re-probe frequencyPartly live Published, 7 September 2026: once per host per 24 hours, for any host we do not own whose operator has not asked us for more. Enforced by the prober before a request is made, and governed real third-party traffic on 7 September 2026, for the 30 probes that ran before probing was paused. It stays Partly live because the published figure has two stated exceptions: hosts we own are probed as fast as our own per-host budget allows, so that the budgets can be observed refusing something — live since 8 September 2026, revision echelon-radar-prober-00066-zsg; and, since 13 September 2026, a domain whose operator proved control by DNS and asked to be monitored is checked no more than once every 30 seconds — at one minute today — which is the next row (#1834). Scoped again 13 September 2026: this row read “for any host we do not own”, and so did the §1.1 sentence it mirrors; a customer’s verified domain is a host we do not own, so the first monitor would have made both false at the exact point they cite as proof, and the sentence gained its second clause in the same commit as the code. Corrected 8 September 2026: this row said “the scheduler asks for one probe per host per 24 hours, so the prober’s own floor has not yet had to refuse anything”. That was false, and measurably so — the prober’s stats line in production shows the floor refusing 713 of 714 fetched jobs against our own domain, which is what a self-test at a five-minute cadence produced against the 24-hour floor a stranger would get. The floor has refused a great deal. The budgets had refused nothing when that correction was written and have since refused 164 of 178, which the budgets row records. Split from the retention row on 7 September, when the two were badged together as live.
Consented monitoring of a verified-owner domainPartly live Ships with this page (#1834). Self-service and sessionless: one DNS TXT record at _echelongraph.<domain> proves control, the screen at /radar/monitor watches up to three domains, and a domain is checked only while a proof is on file (7 days, renewable) and a screen is renewing its 120-second lease. The interval is the published 30-second floor or slower, from a fixed set the operator chooses; the prober applies one minute to every consented domain today and does not yet read the chosen rung. At most 25 domains at once, at most 72,000 checks a day, counted apart from the ceiling for hosts that did not ask, and every other control — robots.txt, budgets, backoff, opt-out, the jurisdiction exclusion — applies unchanged. Whether a given domain is under it is answerable by anyone at GET /api/v1/public/radar/monitor/<domain>. Partly live and not Live today because the cadence an operator chooses is not yet the cadence in force; the floor is.
The public Radar feed itselfLive today The page is live at /radar and the read API serves five endpoints, both since 8 September 2026, and it publishes observations: measured 13 September 2026 against the served API, the overview answered for 2,946 domains over the trailing 24 hours and the per-domain rows carried header grades, HSTS, TLS and certificate facts. What §6 and §7 promise around the feed — removal on a verified exclusion, the disputed marking, suppression of an unreachable record — is graded in its own rows below, and the feed also shows a domain’s registry expiry and status (see What we never do). Corrected 13 September 2026: this row read “It publishes no observations yet: the service holds no credentials for the measurement store, so every panel says it cannot read rather than showing a zero. The store itself holds 30 rows”, badged partly, and all three clauses had stopped being true — this page was re-dated twice over them without the row being re-read. Corrected 8 September 2026: this row read “Not built … /radar returns 404 and the read API has no handlers”, and both halves stopped being true that morning. Corrected 7 September 2026, twice; this row read “No store and no public surface… exists”, then said the store “holds nothing” in the same breath as saying it holds rows — but nothing is published from it, and the retention periods above apply to what it holds.
Dispute intake, and the disputed-observation markingPartly live [email protected] is monitored and a dispute reaches a human today. The marking is not built, and the feed it would appear on is live, so it is now owed rather than deferred. (Corrected 13 September 2026: this read “there is no feed for it to appear on”.)
Dated corrections displayed against an observationNot yet Not built. (Corrected 13 September 2026: this read “for the same reason”, the reason being that no feed existed; one does.)
Tier 2 retroactive removal of published observationsNot yet Not built. Observations are published (the feed row), so the commitment now has something to act on, and nothing yet acts. (Corrected 13 September 2026: this read “there is nothing published to remove yet”.)
Suppression of an “unreachable” observation on requestNot yet Not built. A request at [email protected] reaches a human, and the suppression is done by hand if at all. (Corrected 13 September 2026: this read “for the same reason”, the reason being that no feed existed.)
Corroboration of a certificate from a second vantage point before publicationNot yet Not built.
Scheduled probingLive today Live since 9 September 2026. It ran once on 7 September 2026 against 40 domains, was paused the same day because our sign-off record required six controls recorded as verified running and none had been, and resumed on 9 September 2026 once they were. It now selects every domain in our registry9,619 of 9,999 active rows a day, the difference being the excluded jurisdictions — rather than the one-in-two-hundred sample this row described until 9 September 2026. Measured over the 24 hours to 13 September 2026: 2,446 requests to 2,446 distinct hosts, so one each.
Tier 2 verified exclusion — the registerLive today Self-service for a domain: two public endpoints and one DNS TXT record. A request records nothing; only the DNS proof excludes. The verified list is published every 60 seconds and read by the prober every 30.
Tier 2 verified exclusion — enforcement against a probePartly live The probe engine and the robots fetch each consult an opt-out gate before every request and every redirect hop, that gate fails closed, and on the scheduled path the list it holds is the register itself, reloaded every 30 seconds. Corrected 7 September 2026: this row read “the gate they are given today is a fixed allowlist of our own hostnames, not the register”, which was true of the operator one-shot and had stopped being true of the scheduled path. Partly live and not Live today because nobody has registered an exclusion, so it has never refused a probe.
Tier 1 self-service exclusionPartly live Usable today by blocking the one published address; what is missing is the machine-readable ranges file, and that address carries our other services, so blocking it stops more than Radar. Previously badged notyet, which understated what you can do. Corrected 7 September 2026; this row previously ended “it depends on the source ranges above, which are not published”, which was the retracted claim left in place beside its own correction. [email protected] is monitored today.
Twelve-month re-verification and re-contact of an exclusionNot yet Not built. Nothing expires, so no exclusion can lapse on its own; what is missing is the process that would ask you whether it should continue — and a DNS-verified exclusion records no contact details for us to ask through.

We will not turn scheduled probing on before this page is live at the URL our User-Agent advertises. A bot whose identity link returns 404 does not have an identity.

Contact

Everything on this page — complaints, adjustments, exclusions, disputes[email protected]
The From header on every Radar probe[email protected]
Verify an X-EchelonGraph-Verify receipt — Radar or any of our scannersechelongraph.io/verify-scan
The Discovery Radars, and our own vulnerability disclosure policyechelongraph.io/responsible-disclosure
Our own security.txt (RFC 9116)echelongraph.io/.well-known/security.txt
How we handle personal dataPrivacy Policy
How we secure our own platformSecurity

We hold ourselves to what we ask of others. Our security.txt is published at the location RFC 9116 requires, under /.well-known/, with both mandatory fields — a Contact and an Expires set less than a year ahead — and with Canonical URIs for both the marketing and application hosts.

Where we contact an operator about something we found, we read your security.txt first, as RFC 9116 §5.8 asks. We also observe §5.5: “researchers shouldn't assume that the presence or absence of a 'security.txt' file grants or denies permission for security testing.” A security.txt on your site is a route to a human. We do not read it as authorisation, and we do not read its absence as a refusal — How to opt out is how you refuse.

Policy dated 13 September 2026. This page is informational and not legal advice. Quotations are reproduced verbatim from the cited sources and retain their original spelling. See also: Responsible Disclosure · Verify a scan · Privacy · Security