Dev.to WebDev 🛠 Dev 👁 0 📖 3 min read

Five Impossible Values I Found in Real Windows Battery Reports

Windows can export a detailed battery report with one command: powercfg /batteryreport The resulting battery-report.html looks like clean, structured data. I built a browser-based reader for it, so I assumed par

Windows can export a detailed battery report with one command:

powercfg /batteryreport

The resulting battery-report.html looks like clean, structured data. I built a browser-based reader for it, so I assumed parsing would be the easy part. Then I ran it against real reports from four laptops and found values that are flat-out impossible.

This post covers what those values looked like and the sanity checks I now run before trusting any number from the file.

The four reports

Laptop Design Full charge Health Cycle count
Lenovo 82TS (~2 years) 45,000 mWh 42,650 mWh 94.8% 141
HP ZBook Firefly 14 G7 53,015 mWh 39,189 mWh 73.9% 454
ThinkPad (~10 years) 47,520 mWh 27,380 mWh 57.6% -
ThinkPad (4–5 years use) 99,470 mWh 24,800 mWh 24.9% -

Health is just FullChargeCapacity / DesignCapacity * 100. The interesting part is everything around it.

Problem 1: a row that is 3× too big

One ThinkPad's Battery capacity history table had this row:

2026-10-30   27,380 mWh    47,520 mWh
2026-10-31   83,235 mWh   144,460 mWh   <- ???
2026-11-01   27,380 mWh    47,520 mWh

The ratio is still 57.6%, so a naive health calculation looks fine. But if you chart full charge capacity over time, you get a spike that suggests the battery tripled overnight.

Check: design capacity should be constant for a given battery. If a row's design value differs from the median design value by more than a few percent, flag the whole row.

function flagDesignOutliers(rows) {
  const designs = rows.map(r => r.design).sort((a, b) => a - b);
  const median = designs[Math.floor(designs.length / 2)];
  return rows.map(r => ({
    ...r,
    suspect: Math.abs(r.design - median) / median > 0.05
  }));
}

Problem 2: 67 years of AC time in one week

The Lenovo's Usage history section listed an AC duration of 592618:40:06 for a single week. That's about 67 years.

Check: a period can't contain more hours than it spans. Parse the period start and end, compute the maximum possible duration, and reject anything above it.

function hmsToHours(s) {
  const [h, m, sec] = s.split(':').map(Number);
  return h + m / 60 + sec / 3600;
}

function isPlausibleDuration(hms, periodStart, periodEnd) {
  const maxHours = (periodEnd - periodStart) / 3.6e6;
  return hmsToHours(hms) <= maxHours + 1; // 1 h slack for DST and boundaries
}

Problem 3: standby drains over 100% per 16 hours

Laptops with Modern Standby show a connected-standby drain rate like 39 % / 16 h. Across a few weeks, the same Lenovo reported 1 % / 16 h (a 1,929-hour estimate) and 994 % / 16 h. The HP hit 1,061 % / 16 h.

A drain above 100% in 16 hours isn't strictly impossible, but these values swing so wildly week to week that I treat them as noise unless several weeks agree.

Check: show the median across weeks, and label single extreme weeks instead of averaging them in.

Problem 4: the cycle count is a dash

Both ThinkPads report CYCLE COUNT -. It's not zero and not a parsing bug. The firmware simply doesn't expose it to Windows.

Check: treat -, empty, and 0 as "not reported" and say so in the UI. Displaying 0 cycles for a 10-year-old battery is wrong and erodes trust in every other number on the screen.

function parseCycleCount(raw) {
  const n = Number(String(raw).replace(/[^\d]/g, ''));
  return Number.isFinite(n) && n > 0 ? n : null; // null = not reported
}

Problem 5: a single reading can be far off

Even when every row is plausible, one reading can mislead. The older ThinkPad reported 3% health for five months, then about 25% from late September, with nothing done to the battery. The other ThinkPad jumped from 46% to 57.6% in the same few weeks. The most likely cause is the battery's fuel gauge correcting its own estimate.

Check: don't headline the latest value alone. Show the trend from Battery capacity history and point out sudden jumps.

Bonus: number formats

The report uses the system locale. 27,380 mWh on an English system can be 27.380 mWh or 27 380 mWh elsewhere. Strip everything that isn't a digit before parsing integer mWh values, and never parse them with parseFloat directly.

What I took from this

The battery report is the best free source of battery data on Windows, but it's firmware-reported data, not a measurement. Any tool that reads it should:

  1. Validate design capacity per row.
  2. Bound durations by the period length.
  3. Treat extreme standby estimates as noise until confirmed.
  4. Distinguish "not reported" from zero.
  5. Show trends, not just the latest value.

I've published the full numbers from all four laptops, including the glitches, as a small open dataset with a CSV: real laptop battery report data. To read your own report, the battery health checker runs entirely in the browser and doesn't upload the file.

Have you seen impossible values in your own battery report? I'd like to add more examples.

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.