How to Parse Apache Log Files in Python

Parse Apache common log format lines into structured dictionaries using Python's standard library.

Medium Python 3.9+ Aug 9, 2026 Files & data 15 views 0 copies

Python code

44 lines
Python 3.9+
import re
from pathlib import Path

def parse_apache_line(line):
    pattern = r'^(\S+) (\S+) (\S+) \[([^\]]+)\] "(\S+) (\S+) (\S+)" (\d{3}) (\S+)'
    match = re.match(pattern, line)
    if not match:
        return None
    ip, ident, user, timestamp, method, path, protocol, status, size = match.groups()
    return {
        "ip": ip,
        "user": user,
        "timestamp": timestamp,
        "method": method,
        "path": path,
        "status": int(status),
        "size": int(size) if size.isdigit() else 0
    }

def read_apache_log(filepath):
    log_path = Path(filepath)
    if not log_path.exists():
        raise FileNotFoundError(f"Log file not found: {filepath}")
    entries = []
    with log_path.open("r") as f:
        for line in f:
            line = line.strip()
            if line:
                parsed = parse_apache_line(line)
                if parsed:
                    entries.append(parsed)
    return entries

if __name__ == "__main__":
    sample_log = """192.168.1.1 - - [10/Oct/2024:13:55:36 +0000] "GET /index.html HTTP/1.1" 200 2326
192.168.1.2 - john [10/Oct/2024:13:56:02 +0000] "POST /api/data HTTP/1.1" 201 128
10.0.0.5 - - [10/Oct/2024:13:56:45 +0000] "GET /images/logo.png HTTP/1.1" 404 0
"""
    temp_file = Path("/tmp/sample_apache.log")
    temp_file.write_text(sample_log)
    results = read_apache_log(temp_file)
    for entry in results:
        print(entry)
    print(f"Total entries: {len(results)}")

Output

stdout
{'ip': '192.168.1.1', 'user': '-', 'timestamp': '10/Oct/2024:13:55:36 +0000', 'method': 'GET', 'path': '/index.html', 'status': 200, 'size': 2326}
{'ip': '192.168.1.2', 'user': 'john', 'timestamp': '10/Oct/2024:13:56:02 +0000', 'method': 'POST', 'path': '/api/data', 'status': 201, 'size': 128}
{'ip': '10.0.0.5', 'user': '-', 'timestamp': '10/Oct/2024:13:56:45 +0000', 'method': 'GET', 'path': '/images/logo.png', 'status': 404, 'size': 0}
Total entries: 3

How it works

The regex pattern anchors each line to extract exactly the fields of Apache's common log format: IP, identity, user, timestamp, request method, path, protocol, status code, and size. Using re.match with careful escaping handles edge cases like - for missing user fields. The Path.open context manager ensures the file closes cleanly, while strip() removes trailing newlines. Converting status and size to integers makes downstream analysis (like filtering by HTTP code) straightforward.

Common mistakes

  • Forgetting to strip trailing newline characters before matching
  • Assuming size is always numeric — need `isdigit()` fallback for missing values
  • Using `re.search` instead of `re.match` causing unexpected matches mid-line

Variations

  1. Use `namedtuple` or `dataclass` instead of dict for typed access
  2. Stream parse with a generator for large logs to avoid memory issues

Real-world use cases

  • Security analysis: extract IPs and paths to detect suspicious traffic patterns in production
  • Monitoring dashboards: parse frontend server logs to display real-time request rates by endpoint
  • Data pipelines: ingest web server logs into analytics systems for user behavior modeling

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Files & data

Related tutorials and quizzes for this topic.