How to Allocate Proxy Costs Across Teams and Clients
Allocate proxy costs fairly: four chargeback models, how one $240 plan produces bills differing 4.8x, and how to tag usage at the request instead of guessing.

To allocate proxy costs you have to solve a unit problem before you solve an accounting one: you buy concurrency, credits or gigabytes, and you bill teams, projects or clients, and those two things do not line up on their own. Pick the wrong translation and the same unchanged invoice produces per-client charges that differ by nearly five times.
This is the layer above capacity planning. Our guide to proxies for marketing agencies covers running many clients off one plan and sizing it. This one covers what happens when finance asks who owes what, and it applies as much to internal cost centres as to external clients.
The short answer
Allocate along whichever resource is actually scarce, and split the rest evenly. If concurrency is your binding constraint, charge for reserved threads. If you are on a credit plan, charge for credits consumed. If nothing is scarce because the plan is comfortably oversized, stop building a cost model and divide by headcount, because the allocation will cost more in argument than it recovers in accuracy.
Then add two rules that matter more than the model you chose. Attribute usage at the moment of the request, not from a spreadsheet at month end. And publish the numbers for at least one quarter before anybody is billed on them.
What you buy is not what you bill
Every proxy plan sells one of four units, and none of them is the unit your finance system wants. The mechanics of each are in datacenter proxy pricing models and the current market rates in how much proxies cost.
| What the plan sells | What moves the bill | What teams think they consume |
|---|---|---|
| Concurrent threads, flat monthly | Nothing, until you outgrow the tier | Requests, or "the scraper" |
| Credits per month | Rendering, geo-targeting and premium exits | Pages collected |
| Gigabytes transferred | Page weight, which they do not control | Records extracted |
| IP addresses per month | Address count, driven by the target | Accounts or projects |
The mismatch is the whole problem. On a flat concurrency plan the marginal cost of one more request is zero, so a usage-based allocation is charging for something that did not cost anything. On a per-GB plan the marginal cost is real and page weight drives it, so a per-request allocation charges the team scraping lightweight JSON the same as the team pulling image-heavy product pages. If that is your situation, allocating by bytes and pairing it with reducing proxy bandwidth costs will recover more than any billing policy.
The honest framing for internal conversations: you are not recovering a marginal cost, you are apportioning a shared fixed cost. Say that out loud early. It changes the argument from "prove I caused this" to "agree a fair share", which is a much shorter meeting.
Scraping at scale? Skip the blocks.
Fast, unblockable datacentre proxies with unlimited bandwidth.
Four allocation models, and what each one rewards
| Model | Basis | Rewards | Punishes | Best when |
|---|---|---|---|---|
| Even split | Headcount, team count or client count | Nothing | Small consumers | The plan is oversized and nobody is near a limit |
| Reserved capacity | Threads, concurrency or credits committed in advance | Releasing capacity you do not need | Teams that reserve defensively and never use it | Concurrency is the binding constraint |
| Metered usage | Requests, credits or bytes actually consumed | Efficiency, caching, finding the JSON endpoint | Nobody, until a team stops collecting data it needs | You have per-request attribution and real scarcity |
| Base plus usage | A fixed platform fee, then a variable component | Both predictability and efficiency | Anyone who wanted one number | Most real teams, most of the time |
The fourth is what most organisations converge on, and the reason is political rather than technical. A pure metered model makes every month's number a surprise, which finance dislikes. A pure even split makes the largest consumer invisible, which everybody else dislikes. A fixed base that covers the plan's floor plus a variable component that tracks consumption satisfies both, and the split between them is a policy decision rather than a calculation.
One model to avoid outright: allocating by "value delivered" or by revenue attributable to the data. It sounds fair for about a week and then becomes a negotiation with no ground truth.
One plan, two models, very different bills
Here is why the choice matters more than the arithmetic. One agency, one SparkProxy Boost plan at $240 a month for 500 threads with unlimited bandwidth, six clients. The figures below are an illustrative construction, not measurements from any real account.
Under reserved capacity, each client is allocated a share of the 500 threads, and the plan cost divides at $240 divided by 500, which is $0.48 per thread per month.
Under metered usage, the same clients consumed 3,000,000 requests between them, so the plan cost divides at $240 divided by 3,000,000, which is $0.08 per thousand requests.
| Client | Reserved threads | Bill at $0.48/thread | Monthly requests | Bill at $0.08/1,000 | Change |
|---|---|---|---|---|---|
| Alpha | 150 | $72.00 | 1,200,000 | $96.00 | up 33% |
| Bravo | 100 | $48.00 | 900,000 | $72.00 | up 50% |
| Charlie | 80 | $38.40 | 400,000 | $32.00 | down 17% |
| Delta | 70 | $33.60 | 300,000 | $24.00 | down 29% |
| Echo | 60 | $28.80 | 150,000 | $12.00 | down 58% |
| Foxtrot | 40 | $19.20 | 50,000 | $4.00 | down 79% |
| **Total** | **500** | **$240.00** | **3,000,000** | **$240.00** |
Same invoice, same month, same total. Foxtrot pays $19.20 under one model and $4.00 under the other, a factor of 4.8. Nobody is cheating and no arithmetic is wrong. The two models simply answer different questions: reserved capacity asks what you made us hold available, metered usage asks what you actually took.
Which one is right depends on why you are on Boost rather than Core. If you upgraded because peak concurrency demanded it, the cost was caused by whoever needed the peak, and reserved capacity is correct. If you upgraded because total volume grew, metered usage is correct. Working out which constraint you are actually on is the subject of concurrent connections in proxies and how many proxies you need.
Notice the second-order effect too. Under reserved capacity Foxtrot has an incentive to hand back threads it does not use, which frees real capacity. Under metered usage Foxtrot has an incentive to collect less data, which may be exactly the wrong outcome if that data is valuable.
Tag the request, do not reconstruct the month
Attribution built at month end from logs is always incomplete, and the gaps always get assigned to whoever complains least. Build it at the point of the request instead.
On the SparkProxy Scraping API there is a parameter for exactly this. tag takes a string of up to 128 characters using alphanumerics plus _ - . : @ /, attaches it to the request, and echoes it back in the response so you can group and filter by project, client or feature.
curl -G "https://scrape.sparkproxy.io/api/v1" \
-H "X-API-Key: YOUR_API_KEY" \
--data-urlencode "url=https://example.com/catalog/page/1" \
--data-urlencode "render_js=false" \
--data-urlencode "json_response=true" \
--data-urlencode "tag=client/foxtrot:catalog-sync"
With json_response=true the envelope carries job_id, status_code, duration_ms, credits_used and the tag you sent, which is everything an allocation needs in one record. Write those five fields to your own store as each job completes and the month-end report becomes a group-by rather than an investigation.
Design the tag taxonomy before you use it, because you will not be able to fix history. A workable shape is three segments: who it is for, what it is, and which environment it ran in, for instance client/foxtrot:catalog-sync@prod. Keep the separator characters consistent, never put anything confidential in a tag, and never reuse a tag value for a different purpose after a client leaves.
On a proxy plan rather than the API there is no per-request envelope, so the boundary you get is the credential. Give each team or client its own sub-user and its own whitelist slot so that traffic is separable at the source, which is covered in sub-users and credential rotation and IP whitelisting. Whitelist slots are capped per tier, 5 on Starter, 10 on Core, 15 on Boost and 25 on Plus, so the plan you buy also sets a ceiling on how many parties you can cleanly separate that way. Six clients on Boost fit comfortably. Twenty do not.
Whatever you do, keep an explicit unattributed bucket and charge it to the platform, never to the largest consumer. If unattributed usage passes roughly a tenth of the total, you have an instrumentation defect rather than a billing disagreement, and no allocation policy will fix it.
Somebody has to pay for the headroom
Every well-run plan carries capacity nobody is using, on purpose, so that a burst does not queue behind another team's backfill. That headroom is real and it costs real money, and pretending otherwise is how allocation models lose credibility.
Take the same Boost plan. Allocate all 500 threads and you have no reserve. Allocate 400 and hold 100 back, and the cost per allocated thread rises from $0.48 to $0.60, a 25% increase, because the same $240 is now spread across fewer billable units.
That 25% is not overhead in the pejorative sense. It is the price of every team's jobs finishing on time, and the small consumers benefit from it as much as the large ones, arguably more, since they are the ones who would get queued behind somebody else's backfill. Two defensible ways to handle it:
Load it into the unit rate, as above, so every allocated thread carries its share silently. Simple, and invisible to the teams, which is both the advantage and the disadvantage.
Bill it as a separate platform line, split evenly, so the headroom shows up as its own number. Harder to explain the first time, easier to defend every time after that, and it makes the cost of reliability an explicit decision rather than a hidden markup.
Either is fine. Smearing it proportionally onto the largest consumer is not, because it makes growth look more expensive than it is and quietly discourages the teams doing the most valuable work.
On credit plans, your blended rate falls as you grow
If you are reselling or rebilling a Scraping API plan, this one is worth a note in the policy document.
SparkProxy's credit tiers are Starter at $49 for 250,000 credits, Growth at $99 for 1,000,000, Pro at $249 for 3,000,000 and Scale at $599 for 8,000,000. Divide through and the blended cost per credit is:
- Starter: $0.000196
- Growth: $0.000099
- Pro: $0.000083
- Scale: $0.0000749
That is a fall of about 62% from the entry tier to the largest one. In practical terms, a thousand JavaScript-rendered fetches costs 5,000 credits, which is about $0.50 on Growth and about $0.37 on Scale, roughly 24% cheaper for an identical job.
The implication for rebilling: if you set a client-facing rate card on the tier you were using when you wrote it, your margin grows every time you upgrade, without anyone deciding that it should. That is not dishonest, but it should be a choice. Either pass the tier improvements through at review time, or state plainly that your rate is a service price rather than a cost pass-through. Do not describe it as "at cost" and then keep the tier discount. The mechanics of what each request type consumes are in scraping API credit pricing.
Showback before chargeback
The single most effective thing you can do before billing anybody is to not bill them for a quarter.
Publish a monthly report showing each team or client what they consumed and what it would have cost under the proposed model. Change nothing about the money. Three things happen, reliably:
The instrumentation gaps surface while they are still free to fix. Somebody always discovers that a scheduled job has been tagged to the wrong project since it was written.
Teams self-correct before any invoice exists. A team that sees it is generating 40% of the requests usually finds a cache, a conditional request or a JSON endpoint within a fortnight, which is a better outcome than collecting money from them.
The model gets argued about in the abstract rather than in a dispute over a specific invoice, which is a far more productive conversation and produces a policy people will actually defend afterwards.
Run showback for a quarter, then switch on chargeback with the model that survived the argument. If nothing changed during showback, that is useful evidence that the allocation is not worth doing at all.
When to stop allocating and buy them their own plan
Allocation exists because pooling is cheaper. Once it stops being cheaper, stop allocating.
The test is not "does this client's share exceed the cheapest plan". It is: does their allocated share exceed the price of the smallest standalone plan that meets their peak concurrency? Those are different questions and the second one is the correct one.
Run it on Alpha from the worked example. Alpha's metered share is $96 a month and it reserves 150 threads. The smallest standalone SparkProxy plan that covers 150 threads is Core at $140 a month, since Starter carries 100. So Alpha costs $96 inside the pool and $140 outside it, and pooling saves $44 a month. Alpha stays.
Now imagine a client needing 600 threads whose allocated share came to $500. The smallest plan covering 600 threads is Plus at $440. That client is now paying more for a share of the pool than a dedicated plan would cost, so they get their own plan and everybody's arithmetic gets simpler.
Three non-financial reasons override the arithmetic entirely:
- Isolation requirements. If a client contractually requires that their traffic never shares infrastructure with another client, the decision is made.
- Invoice requirements. Some clients need the provider's own invoice in their name. A share of yours will not satisfy procurement.
- Blast radius. If one client's behaviour can get an address range flagged in a way that breaks everyone else, separating them is a reliability decision, not a billing one.
For very small standalone work, proxies for freelance scraping projects covers the one-person version of this decision.
What belongs on a client invoice
Four practical rules, learned the expensive way by a lot of agencies.
Do not invent a unit you do not buy. If your plan is unlimited bandwidth, do not bill a per-gigabyte rate. The number is fabricated, a client who learns your plan terms will notice, and you have created an argument you cannot win. Bill for the service, or bill a share of a real plan cost. Background on why that unit does not exist on a flat plan is in whether unlimited bandwidth is worth it.
Decide pass-through or marked-up, and say which. Both are legitimate. Presenting a marked-up figure as "at cost" is not, and it is the kind of thing that surfaces during a contract review at the worst possible time.
Keep the line stable enough to be boring. A charge that moves by a few dollars every month generates more finance questions than it recovers in revenue. Banding clients into a small number of tiers and reviewing quarterly beats a precise figure that changes constantly.
Show the basis, not the vendor's pricing. A client is entitled to know what they are paying for and how it was calculated. They are not automatically entitled to your supplier's rate card, and publishing it constrains your own negotiating position at renewal.
A monthly reconciliation you can actually run
Six steps, thirty minutes, once a month.
- Pull the plan invoice total. One number, from the provider.
- Pull your own usage totals by tag or sub-user. Requests, credits, or threads reserved, whichever your model uses.
- Compute the unattributed residual. Total consumption minus the sum of attributed consumption. Log it every month so you can see the trend rather than one month's figure.
- Apply the model. Fixed component split by policy, variable component by share.
- Check three sanity conditions. The allocations sum to the invoice. No allocation is negative. No client moved more than a set threshold, say 30%, against last month without a known cause.
- File the working, not just the answer. Keep the inputs alongside the output. When somebody queries a figure six months later, the question is always "what was the usage", and a number with no inputs behind it cannot be defended.
Step five is the one that earns its keep. A client whose allocation jumps 80% in a month has either changed their workload, which you should know about before they do, or exposed a bug in your attribution, which you want to find before they do.
Frequently asked questions
FAQ
Build your own meter, because the provider has no per-team view of a flat plan. Tag every request or give every team its own sub-user, record consumption as jobs complete, and apportion the fixed monthly cost by share. Remember that you are apportioning a shared fixed cost, not recovering a marginal one, because on a flat plan one extra request costs nothing.
Charge on whichever resource made you buy the tier you are on. If you upgraded because peak concurrency demanded it, reserved capacity is the honest basis. If you upgraded because total volume grew, metered usage is. Picking the wrong one can change an individual client's bill by several times while leaving the total identical.
No, and it is worth being firm about this. A per-gigabyte rate on an unmetered plan is a unit you never purchased, so the figure is invented. Bill a share of the real plan cost, or bill a service fee for the data work, and describe whichever you choose accurately.
Send a tag on every request. The SparkProxy API accepts a label of up to 128 characters and echoes it back in the response, and with json_response=true the envelope also carries credits_used and duration_ms. Store the tag and the credits together as each job finishes and allocation becomes a group-by instead of a reconstruction.
When their allocated share exceeds the price of the smallest standalone plan that would meet their peak concurrency, not merely the cheapest plan available. Isolation requirements, a client needing the provider's invoice in their own name, and the risk one party poses to everyone else's success rate all override the arithmetic.
Stable, explicable and honestly labelled. Show the basis of the calculation, state whether it is a pass-through or carries a margin, band clients into a few tiers instead of recomputing an exact figure every month, and review the bands quarterly. Never present a marked-up figure as cost recovery.
Get 20% off your first month
Premium datacentre proxies with unlimited bandwidth. Use the code at checkout.
Save up to 15% more on quarterly, half-yearly and yearly plans
Related articles
Is Your Network a Residential Proxy Exit? How to Check
After residential proxy traffic was found exiting the White House network, here is how to check if your office is a residential proxy exit and find the device.
CAPTCHA Keeps Coming Back After Solving: How to Fix It
CAPTCHA keeps coming back after solving? The clearance is tied to the IP, User-Agent and TLS that solved it. Solve on a sticky session and reuse the cookies.
Axios Proxy Not Working for HTTPS: Causes and Fixes
Axios proxy not working for HTTPS? Fix EPROTO, the 400 plain HTTP request sent to HTTPS port error and hangs with proxy:false and https-proxy-agent. Tested.
