What page weight is and why every kilobyte counts
Page weight is the total transfer size of every resource a browser loads for a single page: the HTML document, CSS, JavaScript, images, fonts, video and all embedded third-party resources. It is usually measured in kilobytes or megabytes per page view, complemented by the request count - how many individual files are requested at all. Together, these two figures largely determine how quickly a page becomes usable on an average mobile device and connection.
Not every byte weighs the same. According to Google, JavaScript is byte for byte the most expensive resource on the web (web.dev/Google), because the browser must not only download the script but also parse, compile and execute it on the main thread - which is especially costly on low-end devices. A 200 KB image burdens the device far less than 200 KB of JavaScript. So looking at total size alone is not enough: the distribution across resource types decides the real impact on load time.
With compression active (gzip or Brotli), the compressed transfer size travels the wire, and decompressing in the browser produces a larger resource size. A budget should cap the transfer size because that is what crosses the network - for scripts it is worth also watching the decompressed size, since parsing and execution depend on it. XICTRAQ measures the bytes actually delivered to the visitor.
The numbers: how much pages have ballooned since 2015
The long-term trend is unmistakable: pages get heavier year after year. Since 2015 the median page weight has risen by 202.8% (Web Almanac 2025), with 8.4% added in the last year alone (Web Almanac 2025). In parallel, the number of embedded third-party resources keeps growing: the median page includes 83 third-party requests on desktop and 79 on mobile (Web Almanac 2025). Each of those means an extra DNS lookup, a connection setup and a potential point of failure outside your own control.
| Metric | Value (July 2025) | Source |
|---|---|---|
| Median transfer size, mobile | 2,362 KB | Web Almanac 2025 |
| JavaScript per page (median) | 697 KB | Web Almanac 2025 |
| Third-party requests (desktop) | 83 | Web Almanac 2025 |
| Third-party requests (mobile) | 79 | Web Almanac 2025 |
| Page weight growth since 2015 | +202.8% | Web Almanac 2025 |
| Growth in the last year | +8.4% | Web Almanac 2025 |
These median values describe the middle of the distribution - half of all pages sit below, half above. At the top end, many pages carry a multiple of this (Web Almanac 2025). The underlying insight matters most: weight grows not through one big decision but through many small, unobserved increases. That is exactly why a one-off optimization falls short - without continuous measurement the curve creeps back up after every sprint.
Where the ballast comes from: JavaScript, images, fonts, third parties
Four resource types carry most of the weight. Knowing the distribution tells you where optimization and monitoring pay off most.
At a median of 697 KB (Web Almanac 2025), JavaScript is not the largest block but the most impactful one: it blocks the main thread, delays interactivity and directly worsens Core Web Vitals. Bundler misconfigurations, shipped polyfills and unused dependencies quietly inflate its size.
Images often make up the largest byte share of a page (Web Almanac 2025). Uncompressed JPEGs, missing modern formats such as WebP or AVIF, and images without responsive delivery are the usual culprits. A single careless upload can make a page hundreds of kilobytes heavier.
Fonts seem small but add up fast: multiple weights, multiple scripts, multiple formats. If fallbacks and font-display are not set cleanly, they cost not only bytes but layout stability. Self-hosted fonts subset to the characters actually used keep the weight low.
At 79 to 83 requests per page (Web Almanac 2025), embedded tags, widgets and marketing scripts are a prime driver of uncontrolled growth. Each of them may pull in further resources during a silent deploy - observable via script integrity monitoring.
What bloat costs the business
Page weight is not a technical soliloquy but a revenue question. Google reports that 53% of mobile visits are abandoned if a page takes longer than 3 seconds to load (Google). According to Google/SOASTA, the probability of a bounce rises by 32% as load time grows from 1 to 3 seconds, and by 90% as it grows from 1 to 5 seconds (Google/SOASTA). Heavier pages load more slowly on real mobile connections - the link between weight, load time and bounce is direct.
In e-commerce this hits twice: the average documented cart abandonment rate sits at around 70% (Baymard), and slow pages sharpen that pattern. With more than 60% of web traffic already mobile according to industry analyses (Statista), smartphone performance decides commercial success. Add the SEO lever: heavy pages more often miss the LCP target of 2.5 seconds (web.dev/Google) and slip back in the assessment of user experience.
Every extra megabyte lengthens load time on weak connections, raises the bounce rate and depresses conversion. Budgeting and monitoring page weight directly protects reach, rankings and revenue - not just the Lighthouse score.
Defining byte and request budgets
A performance budget is a self-imposed limit that should not be exceeded (web.dev/Google). It makes bloat visible and negotiable: adding a new script means making room elsewhere. Three budget types have proven useful and can be combined:
- Quantity-based: fixed caps on bytes and request count, such as a total transfer size below a defined ceiling and JavaScript within its own sub-budget.
- Time-based: target values for milestones like LCP under 2.5 seconds (web.dev/Google) or time to interactive, measured under realistic conditions.
- Rule-based: minimum scores, for example a Lighthouse performance score that must not fall below a threshold - details in the guide to the Lighthouse score.
A sensible starting point takes the median values of your own industry and sets the budget deliberately below the current value, so the curve stops creeping upward. A simple budget file per resource type works well as a machine-readable basis:
[
{
"path": "/*",
"resourceSizes": [
{ "resourceType": "total", "budget": 2000 },
{ "resourceType": "script", "budget": 500 },
{ "resourceType": "image", "budget": 900 },
{ "resourceType": "font", "budget": 150 },
{ "resourceType": "stylesheet", "budget": 100 }
],
"resourceCounts": [
{ "resourceType": "third-party", "budget": 40 },
{ "resourceType": "total", "budget": 60 }
]
}
]The numbers in this example are deliberately chosen as guide values and should be adapted to your own baseline. What matters is less the exact ceiling than the fact that there is a binding limit at all, against which every deploy is checked.
Monitoring page weight continuously and alerting on it
A budget only takes effect when compliance is measured automatically. A one-off test shows a snapshot, not the gradual rise over weeks. Continuous monitoring loads the page at regular intervals from several regions, measures transfer size and request count per resource type, and raises an alert the moment a value exceeds the budget.
| Aspect | One-off check | Continuous monitoring |
|---|---|---|
| Timing | manual, occasional | automatic, at fixed intervals |
| Detects gradual growth | no | yes, through the trend line |
| Response after a deploy | random, often too late | alert within the next interval |
| Root-cause attribution | laborious | increase per resource type and point in time visible |
| Regression protection | none | a budget breach triggers a notification |
A weight jump often comes with further symptoms: an oversized bundle can slow the server response or provoke timeouts, visible via server error rate monitoring. That is why XICTRAQ complements page weight monitoring with multi-channel alerting and with reports and status pages that document the trend over weeks. A single measurement thus becomes an early-warning system.
When a deploy quietly ships 400 KB
The most dangerous increases are the unintended ones. Typical triggers for a sudden jump after a release:
- A dependency is updated and brings a larger bundle variant or additional language packs.
- Tree shaking stops working after a configuration change, so unused code ships along.
- An image is uploaded without compression or a modern format and lands in the delivery path at full size.
- A new marketing or analytics tag is added and in turn pulls in further scripts.
- Source maps or debug artifacts accidentally end up in the production bundle - akin to the unintended deploy-leak pattern described in the piece on accidentally shipped noindex tags.
More scripts mean more attack surface. According to industry analyses, exploiting known, unpatched vulnerabilities is among the most common attack paths (Verizon DBIR), and outdated frontend libraries are a favored target. Germany's BSI recommends keeping the embedded third-party landscape small and current (BSI). How to hunt down vulnerable packages is covered in the piece on vulnerable JavaScript libraries.
A budgeting process in five steps
- Take stock: measure the current transfer size and request count of your most important pages per resource type - homepage, product and category pages, checkout.
- Set the budget: define realistic but binding ceilings just below the actual value, split by total weight, JavaScript, images and third-party requests.
- Bank the quick wins: convert images to modern formats, subset fonts, remove unused code and serve static assets via a CDN.
- Set up monitoring: have the budgets checked automatically and regularly, with an alert on every breach instead of manual spot checks.
- Watch the trend: evaluate the trajectory over weeks, catch gradual increases early and treat a budget breach like a bug, not a footnote.
Setting up page weight monitoring with XICTRAQ
Page weight is not a static value you optimize once and forget. It changes with every deploy, every new dependency and every embedded third-party script. So monitoring belongs in the same toolbox as controlling load times: measure, budget, alert.
XICTRAQ measures transfer size and request count per resource type from several regions, compares them against your budgets and notifies you the moment a deploy breaks the ceiling - combined with performance monitoring, Lighthouse audits and Core Web Vitals tracking. So you see the increase on release day instead of weeks later in the conversion figures.
Start with a free trial and check how heavy your most important pages really are today. Or book a personal demo to see budgets and alerting in action.
This article draws on data from: Web Almanac 2025 / HTTP Archive (mobile page weight 2,362 KB, +8.4% in the year, +202.8% since 2015, JavaScript median 697 KB, 83/79 third-party requests desktop/mobile), web.dev / Google (JavaScript as the most expensive resource, LCP target 2.5 s, performance budgets, 53% abandonment above 3 s load time), Google / SOASTA (rise in bounce probability with load time), Baymard (cart abandonment around 70%), Statista (share of mobile web traffic), Verizon DBIR (exploitation of known vulnerabilities), BSI (reducing third-party attack surface). Legal statements do not constitute legal advice.