Analyzing Laptop Battery Health on Windows Systems

The battery health percentage is calculated by comparing the current full charge capacity against the original design capacity, both measured in milliwatt-hours (mWh).

Here's a Python implementation that extracts battery health information from Windows battery reports:

import re
from pathlib import Path

def parse_battery_metrics(html_text):
    """
    Extract battery metrics from Windows battery report HTML
    
    Args:
        html_text (str): HTML content of battery report
        
    Returns:
        tuple: (design_capacity, current_capacity, health_ratio, charge_cycles)
    """
    # Pattern for original design capacity
    design_pattern = r'DESIGN CAPACITY[\s\S]*?>([\d,]+)\s*mWh'
    # Pattern for current maximum capacity
    current_pattern = r'FULL CHARGE CAPACITY[\s\S]*?>([\d,]+)\s*mWh'
    # Pattern for charge cycle count
    cycle_pattern = r'CYCLE COUNT[\s\S]*?>([\d,]+)'
    
    design_mwh = None
    current_mwh = None
    cycles = None
    
    # Extract design capacity
    design_match = re.search(design_pattern, html_text, re.IGNORECASE)
    if design_match:
        design_mwh = int(design_match.group(1).replace(',', ''))
    
    # Extract current capacity
    current_match = re.search(current_pattern, html_text, re.IGNORECASE)
    if current_match:
        current_mwh = int(current_match.group(1).replace(',', ''))
    
    # Extract cycle count
    cycle_match = re.search(cycle_pattern, html_text, re.IGNORECASE)
    if cycle_match:
        cycles = int(cycle_match.group(1).replace(',', ''))
    
    # Calculate health percentage
    health_pct = None
    if design_mwh and current_mwh and design_mwh > 0:
        health_pct = (current_mwh / design_mwh) * 100
    
    return design_mwh, current_mwh, health_pct, cycles

def assess_battery_health(file_path):
    """
    Read and analyze battery report file
    
    Args:
        file_path (str): Path to HTML battery report
        
    Returns:
        dict: Battery assessment results
    """
    try:
        with open(file_path, 'r', encoding='utf-8') as file:
            html_data = file.read()
        
        design, current, health, cycles = parse_battery_metrics(html_data)
        
        if design is None or current is None:
            return {
                'valid': False,
                'message': 'Battery capacity data not found',
                'metrics': None
            }
        
        assessment = {
            'valid': True,
            'message': None,
            'metrics': {
                'design_mwh': design,
                'current_mwh': current,
                'health_pct': round(health, 2) if health else None,
                'charge_cycles': cycles,
                'design_formatted': f"{design:,} mWh",
                'current_formatted': f"{current:,} mWh",
                'condition': evaluate_condition(health) if health else None
            }
        }
        
        return assessment
        
    except FileNotFoundError:
        return {
            'valid': False,
            'message': f'File not found: {file_path}',
            'metrics': None
        }
    except Exception as e:
        return {
            'valid': False,
            'message': f'File reading error: {str(e)}',
            'metrics': None
        }

def evaluate_condition(percentage):
    """
    Determine battery condition based on health percentage
    
    Args:
        percentage (float): Battery health percentage
        
    Returns:
        str: Condition assessment
    """
    if percentage >= 90:
        return "Excellent"
    elif percentage >= 80:
        return "Good"
    elif percentage >= 70:
        return "Fair"
    elif percentage >= 60:
        return "Poor"
    else:
        return "Replace Soon"

def create_battery_report():
    """
    Generate Windows battery report
    
    Returns:
        str: Path to generated report file
    """
    try:
        import subprocess
        subprocess.run(['powercfg', '/batteryreport', '/output', 'battery-report.html'], 
                      capture_output=True)
        
        if Path("battery-report.html").exists():
            return Path("battery-report.html").resolve()
        else:
            return None
    except Exception as e:
        print(f"Report generation failed: {e}")
        return None

def display_results():
    """
    Main function to coordinate battery health analysis
    """
    print("Windows Battery Health Analyzer")
    print("=" * 40)
    
    # Locate existing battery report
    report_files = list(Path('.').glob('battery-report.html'))
    
    if not report_files:
        print("Generating battery report...")
        report_path = create_battery_report()
        
        if not report_path:
            print("Report generation failed. Run with administrator privileges.")
            return
        print(f"Report created: {report_path}")
    else:
        report_path = str(report_files[0])
        print(f"Using existing report: {report_path}")
    
    print("\n" + "-" * 40)
    print("Analyzing battery data...")
    print("-" * 40)
    
    # Process battery report
    analysis = assess_battery_health(report_path)
    
    if not analysis['valid']:
        print(f"Error: {analysis['message']}")
        return
    
    metrics = analysis['metrics']
    
    print(f"\nBattery Metrics:")
    print(f"  Design Capacity: {metrics['design_formatted']}")
    print(f"  Current Capacity: {metrics['current_formatted']}")
    print(f"  Charge Cycles: {metrics['charge_cycles']}")
    print(f"  Health Percentage: {metrics['health_pct']:.2f}%")
    print(f"  Condition: {metrics['condition']}")
    
    print("\n" + "=" * 40)
    print("Recommendations:")
    
    health = metrics['health_pct']
    if health >= 80:
        print("  ✓ Battery condition good - continue normal use")
    elif health >= 60:
        print("  ⚠ Moderate battery health - optimize usage")
        print("     - Avoid prolonged full charge storage")
        print("     - Prevent complete battery discharge")
        print("     - Maintain proper power management settings")
    else:
        print("  ✗ Poor battery health - consider replacement")
        print("     - Contact device manufacturer")
        print("     - Use AC power when possible")
    
    # Calculate estimated remaining capacity
    if health:
        estimated_capacity = metrics['design_mwh'] * health / 100
        print(f"\nEstimated Available Capacity: {estimated_capacity:,.0f} mWh")
    
    print("=" * 40)

if __name__ == "__main__":
    display_results()

This script provides comprehensive battery health analysis with the following capabiltiies:

  • Automatic battery report generation and location
  • Extraction of capacity metrics from HTML reports
  • Health percentage calculation
  • Charge cycle counting
  • Condition assessment with descriptive ratings
  • Usage recommendations based on health status
  • Comprehensive error handling
  • Formatted output display

To use the tool:

  • Execute the script - it will automatically locate existing battery reports
  • If no report exists, the script generates one automatical
  • Administrator privileges may be required for report gneeration

Sample output:


Windows Battery Health Analyzer
========================================
Generating battery report...
Report created: C:\Users\User\battery-report.html

----------------------------------------
Analyzing battery data...
----------------------------------------

Battery Metrics:
  Design Capacity: 45,000 mWh
  Current Capacity: 32,290 mWh
  Charge Cycles: 73
  Health Percentage: 71.76%
  Condition: Fair

========================================
Recommendations:
  ⚠ Moderate battery health - optimize usage
     - Avoid prolonged full charge storage
     - Prevent complete battery discharge
     - Maintain proper power management settings

Estimated Available Capacity: 32,290 mWh
========================================

Run the script from command line:

python battery_analyzer.py

Tags: Windows python battery-health powercfg battery-report

Posted on Wed, 27 May 2026 19:49:41 +0000 by ermajn