Short answers
What counts as proxy traffic?
Every byte through the gateway on your credentials, in both directions: the request line and its headers, the body you send, the response headers, the response body, and the transport overhead underneath them. Traffic is counted in both directions at the gateway, and the figure in the dashboard refreshes every five minutes.
Do request and response headers count?
Yes, and on a small request they are most of it. A browser-shaped header block with a cookie jar is commonly one to two kilobytes per request, and the response headers add a few hundred bytes more. Fetching a 3 kB JSON endpoint ten thousand times is a header bill as much as a data bill.
Does the TLS handshake cost traffic?
Yes. A new HTTPS connection carries a certificate chain and key exchange before any of your bytes move, usually a few kilobytes. It is charged once per connection, not per request, which is why keep-alive costs less than opening a fresh connection for every fetch.
Does a failed request still use traffic?
If it reached the destination, yes. A 403, a 404, a redirect chain and a page that half-loaded before your timeout all moved real bytes and are all metered. A request the gateway itself refuses is different: it never left us, and the whole exchange is a few hundred bytes.
Does compression reduce what I am charged?
The meter sees the bytes on the connection, so a response that arrives gzip or brotli compressed is counted at its compressed size, not at the size your client expands it to. Sending Accept-Encoding and letting the server compress is the cheapest change you can make.
Why do two runs of the same job use different amounts?
Different retries, different redirects, different advertising and experiment variants, and different caching. A run that opened one connection per page also paid for one handshake per page. Log the bytes per request rather than guessing which of those it was.
Where do I see my own usage?
GET /v1/traffic returns gb_total, gb_used and gb_left, the same figures the dashboard shows, refreshed every five minutes. An alert fires at 80 percent of the balance and again when it is used up, by email and by webhook as usage.80pct and usage.cap_reached.
What the meter counts
The gateway counts bytes on your connection in both directions. Upload counts: a POST body, an uploaded file, the headers you send. Download counts: everything that comes back, whether your code reads it or discards it.
What happens on your own machine afterwards is free. Parsing, screenshots written to disk, a database write, a retry that never leaves your process: none of that passes the gateway, so none of it is metered.
HEAD request pays for headers only. On a crawl that exists to notice changes, checking ETag or Last-Modified first and fetching only what moved is often the single biggest saving available.The parts people forget
| What | Roughly | Charged |
|---|---|---|
| Request headers with cookies and a user agent | 0.5 to 2 kB | Per request |
| Response headers | 0.2 to 1 kB | Per request |
| TLS handshake, including the certificate chain | 2 to 6 kB | Per connection |
| A redirect you follow | A full small response, then the next request | Per hop |
CONNECT to open a tunnel for an HTTPS URL | A few hundred bytes | Per connection |
Redirects are the quiet one. A three-hop chain to a product page is four requests, four header blocks and, if the hops cross hostnames, more than one handshake. Following redirects is usually right; counting them as free is not.
What one page really costs
A plain HTTP fetch of server-rendered markup is tens of kilobytes. The same URL opened in a headless browser pulls images, fonts, stylesheets, scripts, analytics and advertising tags, and lands in megabytes. The gap between those two numbers is usually a factor of ten or more, and it is the largest lever you have.
The sizing arithmetic, with worked examples, is in the GB planning guide. The interception code that closes the gap is in cutting bandwidth in a headless browser.
Retries, failures and what the gateway refuses
Draw the line at the gateway. Anything the destination answered moved what it transferred, however useless the answer was. Anything the gateway refused before forwarding is a status line and a header block, and cannot move a balance in any noticeable way.
| Answer | Reached the destination | Bytes involved |
|---|---|---|
407 E_AUTH_INVALID or E_CAP_EXCEEDED | No | The refusal itself, a few hundred bytes |
400 E_USERNAME_PARSE | No | The refusal itself |
502 E_NO_STOCK_COUNTRY | No | The refusal itself |
429 E_RATE_LIMITED_CONN or E_SESSION_LIMIT | No | The refusal itself |
| A 403 or a challenge page from the site | Yes | The whole response, headers and body |
| A timeout after a partial response | Yes | Everything that arrived before you gave up |
This is why a job with a poor success rate costs more than its page count suggests: at a two-in-three success rate you are paying for half again as many responses as you keep. Retry with backoff, cap the attempts, and read the error code before retrying at all. The codes are listed on the setup docs.
Measure it instead of guessing
curl will report what a single request moved, which is enough to build an estimate for a whole run before you commit to it.
These are client-side transfer counters, not the account billing meter. Redirects, protocol overhead and other requests can make the totals differ.
curl -s -o /dev/null \
-x "http://gw.portproof.org:7000" \
--proxy-user "USERNAME-peer-us-rot-ondemand:$PROXY_PASSWORD" \
-w 'sent:%{size_request} hdr:%{size_header} body:%{size_download} up:%{size_upload} redirects:%{num_redirects}\n' \
-L https://example.com/
# the same URL without compression, to see what Accept-Encoding is worth
curl -s -o /dev/null -H 'Accept-Encoding: identity' \
-x "http://gw.portproof.org:7000" \
--proxy-user "USERNAME-peer-us-rot-ondemand:$PROXY_PASSWORD" \
-w 'uncompressed body:%{size_download}\n' https://example.com/For a real job, log the same numbers per request and reconcile them against the account meter at the end. The two will not match exactly, because your client cannot see the transport overhead underneath it, and redirects, retries, other workers or measurement timing can also explain a gap. Investigate the run before assigning a cause. Use the calculator to estimate GB from your measured sample; it is a planning estimate, not billed usage.
Usage refreshes every five minutes, so read the balance before the run, wait past a refresh after it, then read again.
import os, time
import requests
API = "https://api.portproof.org/v1"
HEAD = {"Authorization": "Bearer " + os.environ["PORTPROOF_API_KEY"]}
def gb_used() -> float:
r = requests.get(API + "/traffic", headers=HEAD, timeout=10)
r.raise_for_status()
return float(r.json()["gb_used"])
before = gb_used()
# ... run the crawl, the agent run or the test suite here ...
time.sleep(360) # past one refresh window
print("this run cost", round(gb_used() - before, 4), "GB")Watch it without watching it
Alerts exist so nobody has to poll. You get one at 80 percent of the balance and one when it is used up, by email and as the usage.80pct and usage.cap_reached webhook events. When the balance is gone the gateway answers 407 with E_CAP_EXCEEDED, which reads exactly like a bad password until you look at the code.
Point the cap alert at whatever wakes your team, and have the job stop on E_CAP_EXCEEDED rather than retry into it. Proving a credential still works after a top-up takes one command from the curl testing guide.
| Order size | Per GB | Saving |
|---|---|---|
| 1 to 4 GB | EUR 4.50 | |
| 5 to 24 GB | EUR 3.90−13 % | |
| 25 to 49 GB | EUR 3.50−22 % | |
| 50 to 99 GB | EUR 3.20−29 % | |
| 100 to 249 GB | EUR 2.90−36 % | |
| 250 GB and more | EUR 2.50−44 % |
GB never expire. What you buy stays on your balance until you use it; a new purchase adds to the same balance. The trial is 0.5 GB for EUR 2.90, once per customer.
The same meter applies to both pools and every rotation mode: you pay for bytes, not for exits or connections.
Bytes behave the same whichever pool you use, so choose the pool for the job rather than for the bill: mobile 4G/5G or residential, one balance across both, with the per-GB ladder on pricing.
What is not allowed
What is not allowed: measuring and reducing your own traffic is fine, and so is the lawful work it pays for. Deliberately loading a third party to run up their costs, and any use on the declined list, are not. See the acceptable-use policy.