WebPageTest vs RUM for Field Data
There is a trap in the phrase "field data." Teams assume it means one thing — what real users experienced — and then discover their two field sources disagree. A scheduled WebPageTest run from a US-East data center reports an LCP of 2400 ms, while real-user monitoring reports a P75 LCP of 3200 ms on mid-range Android over real cellular for the same URL. Both are "field" numbers; both are correct; they measure different populations under different rules. This page, part of the Comparing Performance Testing Tools reference, explains exactly where scheduled WebPageTest field runs and real-user monitoring (RUM) legitimately differ, and gives you a decision matrix for which one to calibrate each budget from.
The distinction matters because you calibrate a budget from a distribution, and these two sources produce different distributions on purpose. Calibrate a merge-gate threshold from RUM and you will chase a moving, post-deploy target you cannot reproduce in CI. Calibrate your user-facing target from a single WebPageTest profile and you will ship a budget that is honest for one device in one city and wrong for everyone else. Getting this right starts with understanding that WebPageTest, even when run from real locations on real devices, is still a controlled sample — not a census.
Synthetic in the Field Is Not the Full Population
WebPageTest is synthetic, but it does not have to run in your CI container. Public and private WebPageTest instances drive real browsers on real (or accurately shaped) networks from chosen geographies, on a schedule you control. That makes it "synthetic in the field": a repeatable, instrumented measurement taken outside the lab but still from a fixed, chosen set of conditions. RUM, by contrast, is passive — it records whatever device, network, and locale each real session happened to bring, captured through custom performance beacons fired from the page.
The axis that separates them is control versus representativeness. WebPageTest gives you high control and reproducibility at the cost of covering only the profiles you scheduled. RUM gives you the true shape of your audience at the cost of noise, sampling, and the fact that every number arrives after the code has already shipped.
Where the Numbers Legitimately Differ
The systematic gap between the two is not measurement error — it is population and sampling. A scheduled WebPageTest run reports a median-of-runs for a specific device and connection, typically a well-provisioned test agent. RUM reports a percentile of a heavy-tailed distribution that includes cold caches, thermally throttled phones, congested networks, and background CPU contention that no scheduled agent reproduces. That is why the RUM P75 sits above the WebPageTest median, and the RUM P90 sits far above it.
| Dimension | Scheduled WebPageTest field | Real-user monitoring (RUM) |
|---|---|---|
| Sample type | Controlled — chosen device, network, geo | Passive — whatever users bring |
| Statistic produced | Median of N runs per profile | P75 / P90 / P99 of all sessions |
| Determinism | High — repeatable within a few percent | Low — heavy-tailed, needs volume |
| When available | On a schedule, before or after deploy | After deploy, once traffic arrives |
| INP / CLS fidelity | Scripted interactions only, partial | True — captures real interaction and layout |
| Coverage | 2–5 fixed profiles | Full device / network / locale matrix |
| Cost driver | Test-agent minutes per run | Beacon ingestion, storage, aggregation |
| Typical use | Diagnosis, waterfalls, competitor checks | User-facing targets, drift detection |
The chart below plots one URL's LCP measured four ways. The WebPageTest median (2400 ms, Moto G-class agent on emulated Fast 3G) is the tightest, most optimistic number. Aggregating many scheduled WebPageTest runs into a field P75 lifts it to about 2900 ms. The RUM P75 for the same page is 3200 ms on mid-range Android over real cellular, and the RUM P90 stretches to 4600 ms — the tail the controlled sample never sees.
Device, Geo, and Cost Coverage
Coverage is the clearest reason the numbers diverge. A scheduled WebPageTest plan runs a handful of fixed profiles — say a Moto G-class device on Fast 3G from US-East, a Pixel-class device on 4G from EU-West, and a cable desktop from US-West. Everything you learn is precise for those exact profiles and silent about everyone else. RUM samples the entire matrix your traffic actually spans: hundreds of device models, every carrier, every locale, cold and warm caches, all weighted by real session frequency.
Cost pushes in opposite directions. WebPageTest cost is per-run test-agent time: a private instance with a small pool can run every URL against every profile a few times an hour cheaply, but the marginal cost of adding profiles is linear and real. RUM cost is ingestion and storage: the first beacon is nearly free, but a high-traffic site pays for volume, which is why teams apply sampling and roll numbers up through a P75/P99 aggregation pipeline. Neither is "cheaper" in the abstract — WebPageTest scales with the number of profiles and runs, RUM scales with traffic.
Reconciling the Gap: A Calibration Procedure
You do not have to choose one source and ignore the other. Reconcile them with a repeatable procedure, then calibrate each budget from whichever source owns it. The steps below produce a documented offset between your WebPageTest field number and your RUM P75, so a WebPageTest reading can stand in for the field target between RUM refreshes.
First, pull a stable WebPageTest field number by running the same URL and profile several times and taking the median, using the WebPageTest API:
#!/usr/bin/env bash
# median LCP across 5 scheduled WebPageTest runs, one profile
WPT_HOST="https://wpt.internal.example.com"
URL="https://www.example.com/product/"
RUNS=5
curl -s "$WPT_HOST/runtest.php?url=$(python3 -c "import urllib.parse,sys;print(urllib.parse.quote(sys.argv[1]))" "$URL")&location=motog-fast3g:US-East&runs=$RUNS&fvonly=1&f=json&k=$WPT_API_KEY" \
-o /tmp/wpt-submit.json
TEST_ID=$(python3 -c "import json;print(json.load(open('/tmp/wpt-submit.json'))['data']['testId'])")
echo "submitted $TEST_ID; poll $WPT_HOST/jsonResult.php?test=$TEST_ID for medianMetrics.firstView"
Second, compute the RUM P75 for the same URL and device class from your beacon store over a matching window, then measure the offset between the two field numbers:
// Node: derive the documented WPT-to-RUM offset for one URL
const wptFieldP75 = 2900; // ms, median of scheduled WebPageTest runs, Fast 3G Moto G-class
const rumP75 = 3200; // ms, RUM P75, mid-range Android on real cellular
const offsetMs = rumP75 - wptFieldP75;
const offsetPct = ((offsetMs / wptFieldP75) * 100).toFixed(1);
console.log(`offset: +${offsetMs} ms (+${offsetPct}%)`);
// offset: +300 ms (+10.3%)
Third, store the offset as calibration metadata next to the budget, so a WebPageTest field run can predict the RUM P75 without waiting for real traffic. Re-derive it monthly, because device mix drifts:
{
"url": "https://www.example.com/product/",
"metric": "LCP",
"deviceClass": "mid-range-android",
"connection": "fast-3g-emulated",
"wptFieldP75Ms": 2900,
"rumP75Ms": 3200,
"offsetMs": 300,
"offsetPct": 10.3,
"rumP90Ms": 4600,
"recalibratedOn": "2026-07-24"
}
An offset under about 10–15% means your scheduled WebPageTest profile faithfully predicts the RUM P75 on mid-range Android over Fast 3G, and you can lean on WebPageTest between RUM windows. A larger offset means the profile is too optimistic — move it toward a slower device and network, the same throttling logic covered in Percentile-Based Threshold Tuning, rather than papering over the gap by loosening the budget.
A Decision Matrix for Which to Calibrate From
The rule is not "trust WebPageTest" or "trust RUM" — it is "calibrate each budget from the source that owns its question." Use the tree below when you are unsure which one sets a given number.
In practice that resolves to three concrete rules. Set your user-facing target — the number leadership cares about — from the RUM P75 on your dominant device class, currently 3200 ms LCP on mid-range Android over real cellular, with the RUM P90 of 4600 ms noted as the tail to shrink. Set your reproducible reference, the value a scheduled job can re-measure identically, from the WebPageTest field median. And for a low-traffic route that never accumulates enough sessions to yield a stable P75 — think a checkout confirmation seen a few hundred times a day — calibrate from WebPageTest field runs outright, because a percentile computed from a handful of noisy sessions is worse than a controlled measurement. This mirrors the broader lab-versus-field split in the Synthetic Monitoring vs RUM trade-offs guide, applied specifically to two field sources.
Finally, keep the two in a loop rather than a hierarchy. Feed the WebPageTest field median into scheduled continuous performance monitoring so drift is caught reproducibly, and let RUM confirm — every month — that the offset you documented still holds. When the offset widens past 15% on your dominant mid-range Android over Fast 3G profile, that is your signal to re-throttle the WebPageTest profile, not to quietly widen the budget.
Frequently Asked Questions
Is WebPageTest field data the same as RUM field data?
No. WebPageTest run from real locations is still a controlled synthetic sample of a few fixed device and network profiles, producing a median-of-runs. RUM is a passive census of every real session, producing true percentiles. Both are "field" numbers but they measure different populations, which is why a WebPageTest median sits below the RUM P75.
Why is the RUM P75 higher than the WebPageTest median for the same page?
Because RUM includes the slow tail that a scheduled profile never reproduces: cold caches, thermally throttled phones, and congested networks. On a typical product page the WebPageTest median might read 2400 ms LCP on a Fast 3G Moto G-class agent while the RUM P75 is 3200 ms on mid-range Android over real cellular, with a P90 near 4600 ms.
Which source should I calibrate a merge-gate threshold from?
Calibrate the reproducible gate reference from WebPageTest field runs, because a merge gate must re-measure the same value identically. Set the user-facing target from the RUM P75 on your dominant device class, and store the documented offset between them so a WebPageTest reading can predict the RUM number between refreshes.
What if a route has too little traffic for a stable RUM percentile?
Calibrate that route from WebPageTest field runs. A P75 computed from a few hundred noisy sessions per day is less trustworthy than a controlled median from several scheduled runs. Once traffic grows enough to yield a stable percentile, switch the user-facing target back to RUM.
How often should I re-derive the WebPageTest-to-RUM offset?
Monthly is a sensible default, because device and network mix drift over time. If the offset widens past roughly 15% on your dominant mid-range Android over Fast 3G profile, re-throttle the WebPageTest profile toward a slower device and network instead of loosening the budget to hide the gap.