A proxy success rate is legible only with its unit, numerator, denominator, validator, retry policy, and taxonomy version. Change one of those and the number can move while every raw network event stays exactly the same.
Two honest proxy tests can disagree because they are not answering the same question.
Six ways the reported rate changes
1. Request, attempt, or job
A browser job can produce one main-document request, dozens of subresource requests, and more than one physical attempt. “95 successful requests out of 100” is not comparable to “95 completed jobs out of 100.” Pick the operational unit first. Keep job_id, attempt_id, and request role separate so more than one valid view can be calculated later.
2. First attempt or final retry result
A job that fails once and passes on retry is a completed job and a failed first attempt. Job completion tells you whether the system eventually delivered. First-attempt success tells you how much retry budget, time, and traffic it needed. Publishing only the final job result hides that cost. Retries also share route, pool, session, destination, and time-window state, so do not assume they are independent samples.
3. Transport, HTTP, or workload success
For HTTPS through an HTTP proxy, a successful CONNECT means the proxy formed a tunnel. It does not mean the page loaded. RFC 9110 (opens in a new tab) is precise about that boundary. A requested-transfer 2xx means the client received a successful-class HTTP response after tunnel setup. It does not prove which intermediary generated it or that the payload satisfied the task. A 200 can still carry the wrong regional variant, a maintenance document, incomplete data, or a response that fails the declared validator.
Client defaults add another split. On a completed requested transfer, cURL can exit 0 for a 4xx or 5xx unless options such as --fail (opens in a new tab) change status handling. Playwright's page.goto() (opens in a new tab) does not throw merely because a valid response is 404 or 500, while requestfailed (opens in a new tab) is for a request where the browser did not obtain an HTTP response. Transport completion, status, and workload validation belong in separate columns.
4. Started attempts or post-hoc eligible attempts
Removing timeouts, authentication failures, unfinished work, or unsupported scenarios after seeing the result usually raises the percentage. A genuine fixture or harness fault can be excluded, but the rule should exist before the run and the count and reason should be published. Preserve every started attempt in the raw log; a later report can mark a predeclared exclusion without erasing the event.
5. Micro or macro average
A micro average pools all successes and attempts, so high-volume scenario cells carry more weight. A macro average computes each predeclared scenario rate first, then averages the cells. Equal weighting is appropriate only when each cell is intentionally equally important to the claim. If an easy, high-volume workload dominates the sample, the micro result can look much better than an equal-cell macro result. Publish the weighting rule and per-cell x/n.
6. Taxonomy version
An HTTP 403 establishes refusal under RFC 9110 (opens in a new tab). It does not establish bot detection, bad proxy credentials, or provider failure. If one adapter maps the raw 403 to bot_detected and another maps it to http_403, their category charts disagree before the network behavior does. Store the raw fact separately from normalized_outcome, taxonomy_version, and success_definition_id.
One dataset, several correct percentages
The interactive normalizer starts with eight fabricated attempts across six jobs. Edit the aggregate counts locally and watch the headline rates move. The synthetic receipts remain visible so the numerator and denominator never disappear behind the percentage. Nothing is stored or sent.
Normalize the denominator, locally.
Edit one set of aggregate counts and compare the six rates those same events can support.
Aggregate counts stay in this component's memory for this tab. Nothing is stored or transmitted. Never enter credentials, proxy URLs, target names, customer IDs, or session keys.
SYNTHETIC STARTING POINTEight fabricated attempts across six jobs. This is not a provider benchmark.
Same counts, six named rates. The defined values span from 16.7% to 100%. Neither is the
success rate without its definition.
- Response returned
Did the proxy exchange or requested transfer return HTTP?
- Tunnel established
Did the proxy form a tunnel?
- Requested-transfer 2xx
Did the end-to-end transfer return 2xx?
- Validated attempt
Did this physical attempt pass the validator?
- First-attempt job
Did the job pass without a retry?
- Job completion within budget
Did the job pass before its retry budget ended?
Synthetic receipts: eight attempts, six jobs
Fabricated for explanation. These rows are not a provider benchmark.
| Attempt | Job | Adapter | Proxy response | Requested transfer | Validator | Adapter label |
|---|---|---|---|---|---|---|
| A01 | J1 | A | CONNECT 200 | 200 | pass | success |
| A02 | J2 | A | CONNECT 200 | 403 | fail | bot_detected |
| A03 | J3 | B | CONNECT 200 | 403 | fail | http_403 |
| A04 | J4 | B | 407 | none | not reached | proxy_auth |
| A05 | J5 | A | CONNECT 200 | 200 | fail | content_invalid |
| A06 | J5 | A | CONNECT 200 | 200 | pass | success |
| A07 | J6 | B | CONNECT 200 | 429 | fail | rate_limited |
| A08 | J6 | B | CONNECT 200 | 200 | pass | success |
| Definition | Fraction | Question it answers |
|---|---|---|
| Any proxy-layer HTTP response | 8/8 = 100% | Did the proxy return CONNECT success or an HTTP challenge? |
| Tunnel established | 7/8 = 87.5% | Did CONNECT form a tunnel? |
| Requested-transfer 2xx, end to end | 4/8 = 50% | Did a started attempt receive a post-tunnel 2xx? |
| Requested-transfer 2xx, given a tunnel | 4/7 = 57.1% | Once a tunnel formed, did the requested transfer receive 2xx? |
| Validated physical attempt | 3/8 = 37.5% | Did the individual attempt pass the workload validator? |
| Job completed within two attempts | 3/6 = 50% | Did the job finish inside its retry budget? |
| First-attempt job success | 1/6 = 16.7% | Did the job pass without a retry? |
- Definition
- Any proxy-layer HTTP response
- Fraction
- 8/8 = 100%
- Question it answers
- Did the proxy return CONNECT success or an HTTP challenge?
- Definition
- Tunnel established
- Fraction
- 7/8 = 87.5%
- Question it answers
- Did CONNECT form a tunnel?
- Definition
- Requested-transfer 2xx, end to end
- Fraction
- 4/8 = 50%
- Question it answers
- Did a started attempt receive a post-tunnel 2xx?
- Definition
- Requested-transfer 2xx, given a tunnel
- Fraction
- 4/7 = 57.1%
- Question it answers
- Once a tunnel formed, did the requested transfer receive 2xx?
- Definition
- Validated physical attempt
- Fraction
- 3/8 = 37.5%
- Question it answers
- Did the individual attempt pass the workload validator?
- Definition
- Job completed within two attempts
- Fraction
- 3/6 = 50%
- Question it answers
- Did the job finish inside its retry budget?
- Definition
- First-attempt job success
- Fraction
- 1/6 = 16.7%
- Question it answers
- Did the job pass without a retry?
The range is 16.7% to 100%, and nothing in the event table changed. The 8/8 reading says only that the proxy returned an HTTP response during CONNECT. A 407 is still a response; it is not a successful tunnel or completed workload. The 4/7 conditional rate is useful for tunnel-established diagnostics, but it removes the failed authentication attempt and must not replace 4/8 when reporting the end-to-end requested-transfer 2xx rate. For a purchasing decision, use the predeclared validated-attempt or completed-job metric that matches the workload.
The raw fact can outlive the label
In one authorized production system, two browser-worker adapters assigned different normalized labels to the same observable condition: an HTTP 403 without an explicit cause flag. One recorded bot_detected. The other recorded http_403. The raw fact was stable; the taxonomy was not.
When publishing a similar example, disclose only what establishes the semantic drift. Remove target, customer, engine, and target-specific rule details.
Store evidence before interpretation
run_id, scenario_id, job_id, attempt_id, attempt_index
provider_product_alias, client_adapter, client_version
request_role, requested_geo, session_policy
started_at, timeout_budget_ms, concurrency
proxy_response_status, requested_transfer_status
transport_error_namespace, transport_error_code
validator_id, validator_version, validator_pass
raw_assertion_evidence, duration_ms, stage_reachedSeparating raw evidence from the taxonomy lets you rerun a new classification over old events. It also lets a reviewer decide whether the network changed or only the label did.
Publish the full metric contract
- Freeze target class, geography, client, timeout, concurrency, session policy, and validator for every candidate.
- Interleave paired tests inside the same time window.
- Use an equal-cell macro average only when every scenario cell is intentionally equally important; otherwise publish the predeclared weights and estimand.
- Also publish the micro rate, retry-assisted job completion, tunnel and transfer-response rates, and raw x/n for each.
- Exclude only predeclared harness or fixture faults, with every excluded count and reason disclosed.
- Keep raw HTTP status separate from inferred cause; attribution stays unknown unless controls or authorized owner evidence support it.
Print the fraction next to every percentage. Also print the target mix, test window, sample count, timeout, client version, retry budget, validator, taxonomy version, and exclusions. A legacy all-attempt pass rate may remain useful for a trend inside one stable harness; it is not interchangeable with a normalized first-attempt rate from another system.
Use the 30-minute workload benchmark to produce a controlled first sample, the status-code guide to preserve protocol facts, and the cURL versus Playwright diagnostic when clients disagree.
Place every provider percentage beside current rankings, underlying reports, and the public methodology. A number without that contract is not ready to compare.