Per-GB proxy billing counts request headers, TLS, redirects and failed responses, not just the page body. Here is every component, and how to audit it.
· 14 min read · Pricing and economics
Proxy bandwidth billing is easy to state and hard to predict. Providers count traffic in gigabytes crossing the connection, in both directions, whether or not the bytes were useful to you. Every page in this market advertises a price per gigabyte. Almost none of them define the gigabyte. That gap is where budgets break: you model the size of the pages you want, you buy against that model, and the invoice arrives 30 to 60 percent higher than the model said.
This article defines the unit. Component by component, with the commands that let you count it yourself.
Start from the mental model that causes the problem. Most people budget as if they are buying documents. Ten thousand product pages at 80 KB each is 800 MB, so buy a gigabyte and go.
The meter does not see documents. It sees a socket. Bytes go up the socket to the target and bytes come back down it, and both directions are traffic. A request you sent is billable even though nothing came back. A response you threw away is billable because it arrived. A redirect that took you somewhere you did not want to go is billable twice — once for the redirect, once for the destination.
Three consequences follow immediately, and they are the three that surprise people:
Here is everything that can land inside a single billed request. Sizes vary by client, target and protocol version, so the column that matters is not the number — it is whether the component is under your control.
| Component | Direction | Under your control? | Notes |
|---|---|---|---|
| TCP connection setup | both | Partly | Amortized if you reuse connections. Paid again on every new connection. |
| TLS handshake | both | Partly | Dominated by the server's certificate chain, which you do not choose. Session resumption removes most of it on later connections. |
CONNECT tunnel establishment |
both | No | For HTTPS through an HTTP proxy, the tunnel is set up before the request exists. |
| Request line and headers | up | Yes | Cookies, User-Agent, Accept-*. A fat cookie jar is pure cost on every request. |
| Request body | up | Yes | POST/GraphQL payloads. Usually small, occasionally not. |
| Response headers | down | Partly | Set-Cookie chains and security headers are larger than people expect. |
| Response body | down | Yes | The only part you actually wanted. Compressible. |
| Each redirect hop | both | Partly | A 301 is a full request/response cycle with headers on both sides. |
| Retransmits and keepalives | both | No | Depends on where the meter reads. Ask. |
The single most useful reframing: you are not billed for a page, you are billed for a conversation. The page is one turn in it.
Do not take a vendor's byte breakdown on faith, including this one. Produce your own:
curl -s -o /dev/null \
-w 'req_line+hdrs=%{size_request}\nreq_body=%{size_upload}\nresp_hdrs=%{size_header}\nresp_body=%{size_download}\nredirects=%{num_redirects}\ntotal_time=%{time_total}\n' \
-H 'Accept-Encoding: gzip, br' \
-L 'https://example.com/some/product/page'
Add the four size fields together and you have the HTTP-layer cost of one
fetch. Run it with -L and without, and the difference is what your redirect
chain costs. Run it with and without the Accept-Encoding header and the
difference is what compression is saving you — see
how to cut proxy bandwidth costs for what
to do when a server ignores it.
Two calibration points for the response-body half of that sum, from a source that publishes its method rather than asserting a range. The HTTP Archive's 2025 Web Almanac page weight chapter, from its July 2025 crawl, puts the median home page at 2,559 KB on mobile and 2,862 KB on desktop (Figure 14.1). Inside that same median home page, HTML is 22 KB (Figures 14.5 and 14.6). The remaining 2.5 MB is images, JavaScript, CSS and fonts. Whether you pay for it is decided entirely by whether your client fetches subresources.
That is the whole headless-browser question in one sentence, and it is why the same crawl can cost more than a hundred times as much depending on the client you point at it — the per-page-type arithmetic is in measured bandwidth by page type.
The table above deliberately carries no byte sizes for the request and TLS
components, because no public dataset publishes them and this article will not
invent them. Produce your own: run tcpdump on an uninstrumented host outside
the proxy path, against one target, under three protocol configurations
(HTTP/1.1 with TLS 1.2, HTTP/1.1 with TLS 1.3, HTTP/2 with TLS 1.3). The
per-component split changes enough between those three that a single published
number would mislead you anyway.
Four failure shapes, four very different byte profiles.
Connection refused or DNS failure. Near zero. Nothing was tunneled. DNS itself is resolved by the exit, not billed as your traffic by most designs — confirm with your provider rather than assuming.
407 or another auth rejection. Headers only, in both directions. Small,
but it happens once per misconfigured worker per attempt, and misconfigured
workers retry fast.
403 or 429 with a challenge body. The expensive one. A modern bot-
management interstitial is a real HTML document with inline JavaScript. You
paid the handshake, the request, the response headers and the body — and got
nothing parseable.
Timeout mid-body. You pay for what arrived. A stream that dies at 60 percent of a 3 MB asset cost you roughly 1.8 MB and produced no record.
Failed requests deserve their own treatment, because at scale they are not an edge case — they are a line item. Failed requests are billed too, and that article takes each of the four classes apart with a retry budget that survives contact with a per-GB plan.
This is the arithmetic that decides whether a project is viable, and it is arithmetic, not a statistic. No measurement required.
If you need N gigabytes of usable data and your success rate is s, you are billed for approximately N / s gigabytes, before retries change anything about s.
Take a 10 TB collection target:
| Success rate | Billed volume | Overhead vs. the target |
|---|---|---|
| 95% | 10.53 TB | +0.53 TB |
| 90% | 11.11 TB | +1.11 TB |
| 70% | 14.29 TB | +4.29 TB |
| 50% | 20.00 TB | +10.00 TB |
| 30% | 33.33 TB | +23.33 TB |
The curve is not linear and that is the point. Moving from 95 to 90 percent costs you half a terabyte. Moving from 50 to 30 percent costs you thirteen. A project that models cost at a healthy success rate and then meets a hardened target does not overrun by a margin — it overruns by a multiple.
Put a price on it. At the residential rate published on the per-gigabyte rates page as of 2026-08-06, $1.99/GB, the same 10 TB of usable data costs $19,900 at a 100 percent success rate and $28,437 at 70 percent. The $8,537 difference bought you nothing. Rates change; check the page rather than this sentence.
This is also why cost per successful request is the only number worth tracking. Cost per gigabyte is a rate card. Cost per successful request is your actual unit economics, and it moves when your blocking rate moves.
A plain HTTP client fetches one document. A headless browser fetches the document and then everything the document references: scripts, stylesheets, fonts, images, analytics beacons, ad tags, video posters. Against the median home page above, that is the difference between paying for 22 KB and paying for 2,559 KB on the same URL.
Sometimes that is the right trade. Rendering defeats some detection, and some data genuinely only exists after JavaScript runs. But it is a trade, and it should be priced before it is made. See what a headless browser costs in gigabytes for the decision table.
Every pricing model is a bet about which variable stays stable. The model does not remove risk; it moves it onto you or off you.
| Model | What it hides | You are exposed to | Best when |
|---|---|---|---|
| Per GB | Success rate | Blocking. Your bill scales with failure. | Page weight is predictable and targets are tolerant. |
| Per IP | Utilization | Idle capacity. You pay for addresses whether or not you use them. | Sustained, steady, high-volume load. |
| Per request | Page weight | Heavy pages. A 5 MB page costs the same as a 5 KB one. | Small, uniform responses — APIs and JSON endpoints. |
| Unmetered | Contention and shaping | Whatever the provider does to keep the plan profitable. | You can test throughput before committing. |
Notice that no model is honest about all three variables at once. Choosing a pricing model is choosing which of your three unknowns you want to be surprised by.
Per-IP pricing hides a second thing: it invites you to reason about a provider's headline pool number, which is unverifiable from outside. The pool figure a vendor prints on its homepage is not a measurement you can reproduce. Budget against your own throughput, not against someone else's count of addresses — the case against buying on pool size is made in full under per-IP pricing hides utilization risk.
Three methods, in increasing order of fidelity. Run at least two. The disagreement between them is informative.
Method 1 — count in the client. The curl -w invocation above, or the
equivalent counters in your HTTP library. Cheapest to run. Reads lowest,
because it sees the HTTP layer and nothing beneath it.
Method 2 — count at a local intermediary. Point your scraper at a local mitmproxy and count there:
# count.py — mitmproxy addon: mitmdump -s count.py
up = down = n = 0
def response(flow):
global up, down, n
n += 1
up += len(str(flow.request.headers)) + len(flow.request.raw_content or b"")
down += len(str(flow.response.headers)) + len(flow.response.raw_content or b"")
print(f"n={n} up={up} down={down} total={up + down}")
This catches traffic your application code never sees — the subresources a browser pulled, the redirect hops your client followed transparently. Still above the transport layer.
Method 3 — count at the socket. Run the job in an isolated network namespace or container and read the interface counters before and after:
cat /sys/class/net/eth0/statistics/rx_bytes /sys/class/net/eth0/statistics/tx_bytes
# ...run the job...
cat /sys/class/net/eth0/statistics/rx_bytes /sys/class/net/eth0/statistics/tx_bytes
This sees everything: TLS records, TCP retransmits, keepalives, ACKs. It is the closest civilian approximation of a wire meter, and it will read higher than your provider if the provider meters at the HTTP layer rather than the socket.
Why your number will differ. Expect a gap in both directions and know which one you are looking at:
CONNECT exchange.A reconciliation within a few percent is normal and not worth chasing. A reconciliation off by 30 percent means one of you is counting a component the other is not, and the five questions below will find it.
One rate rule is published rather than inferred. Traffic routed through advanced Target Filters — state, city, ZIP and ASN — is billed at 2x the standard rate, while country selection and ASN exclusion are included in the base price. Both are documented under country, city and ASN targeting. If you are filtering to a ZIP code out of habit rather than necessity, you are paying double for the habit.
Two gateway-side rejections also show up in traffic accounting discussions:
400 NO_RAY and 407 THREADS_EXHAUSTED. The first
means no exit matched your filter. The second means you hit your plan's
concurrent connection limits. Both are rejections, not
responses from your target.
Everything else about the meter — whether headers and the TLS handshake are counted, whether non-200 responses are billed, where the meter is read — is a question to put in writing to any provider, this one included. That is what the next section is for. Take a written answer, not a sales answer.
Send these as written. The quality of the answer tells you as much as the answer.
403 with a challenge
body, a 429, a connection reset mid-body, and a request that never
received a response.A provider that answers all five in writing is telling you the unit is well-defined internally. A provider that answers in ranges is telling you it is not.
Under a per-GB model, traffic is counted in both directions, so request headers
normally count. This matters most on high-volume, low-payload work: a large
cookie jar and a verbose User-Agent are sent on every single request, and
against a 400-byte JSON response the headers can exceed the payload. Confirm
the exact rule with your provider in writing before you model a job that makes
millions of small calls.
Yes, in every case where a connection was established. The TLS handshake, the
request headers and any response body all crossed the wire before the failure
was known. A 403 served with a bot-management challenge page is the most
expensive failure class, because the challenge is a real HTML document with
inline JavaScript. Only a refused connection or a DNS failure approaches zero
cost.
Measure one representative page with curl -w, summing size_request,
size_upload, size_header and size_download. Multiply by your page count.
Then divide by your expected success rate, and multiply by your average
attempts per URL. That four-step estimate is usually within a reasonable margin
of the invoice. Skipping the success-rate division is the single most common
budgeting error.
Four causes account for most overruns, in order of frequency: retries against a target that has started blocking you, a headless browser downloading subresources you never parse, redirect chains counted per hop, and compression that was requested but not delivered. Measure the response class distribution first. You cannot cut what you have not attributed.
It depends on which variable is stable for you. Per-GB is cheaper for bursty, intermittent or low-volume work, because you pay nothing while idle. Per-IP is cheaper for sustained high-throughput work, because the marginal gigabyte is free once the address is paid for. The break-even point is set by your utilization, not by the headline rate on either plan.
Usually yes. Each hop in a redirect chain is a full request and response with headers in both directions, and following a chain of three means paying for four exchanges to receive one document. Resolve redirect chains once during development, store the final URLs, and request those directly. On a recurring crawl this is one of the easiest reductions available.
Check the per-gigabyte rates before you size the job.
Datacenter, residential and mobile are metered the same way and priced
differently, and the right choice is the cheapest pool that still succeeds
against your target — see
datacenter, residential and mobile pools for the
comparison. Route through gw.anonedge.com:823 and measure your own byte count
from the first request.