Skip to main content
Decoding Fiddler SAZ Files: Parse, Modify & Automate
Advanced Techniques6 min read

Decoding Fiddler SAZ Files: Parse, Modify & Automate

Master Fiddler's SAZ file format: parse, modify, and automate HTTP(S) captures programmatically. Includes C#, Python, FiddlerCore, and HTTPS decryption tips.

Share:

Fiddler’s .saz file format is the de facto standard for saving and sharing HTTP(S) traffic captures — but few developers realize how deeply they can programmatically interact with it. Whether you're building custom test harnesses, automating regression checks for API behavior, or integrating Fiddler debugging into CI/CD pipelines, understanding SAZ internals unlocks powerful automation capabilities beyond manual inspection.

This guide walks through the SAZ format’s structure, demonstrates robust programmatic access using C# and Python, explains how to preserve HTTPS decryption context when reimporting sessions, and highlights common pitfalls that break replay fidelity. You’ll learn not just how to read a SAZ file — but how to treat it as a first-class data source in your toolchain.

What Is a SAZ File — Really?

A .saz file is a ZIP archive containing structured JSON and binary assets. Unlike raw PCAPs or HAR files, SAZ preserves Fiddler-specific metadata: request/response flags (e.g., X-Response-Body-Transformed), custom inspector state, breakpoints, and — critically — decrypted HTTPS response bodies if saved after decryption is enabled. This makes SAZ uniquely valuable for fiddler debugging and long-term HTTP debugging workflows.

Inside the archive, you’ll find:

  • SessionArchive.json: Top-level manifest listing all captured sessions with timestamps, URLs, statuses, and metadata.
  • Raw/: Subfolders (000001, 000002, etc.) containing individual session artifacts:
    • request.txt and response.txt: Plain-text HTTP messages (headers + body)
    • requestbody.txt / responsebody.txt: Raw body bytes (base64-encoded if binary)
    • session.json: Per-session metadata (e.g., ClientIP, ServerIP, IsHTTPS, X-ConnectionID)
  • CustomRules.cs: Optional — only present if saved with FiddlerScript modifications enabled.

💡 Note: SAZ files do not store private keys or certificate material. HTTPS decryption must be re-enabled in the target Fiddler instance before replaying encrypted sessions — otherwise, decrypted bodies will appear as encrypted blobs or fail to load.

Step-by-Step: Reading a SAZ File in C#

FiddlerCore includes SessionArchive APIs, but for standalone parsing (e.g., in build scripts or analysis tools), use System.IO.Compression.ZipFile + Newtonsoft.Json.

Prerequisites

  • .NET 6+ SDK
  • NuGet packages: Newtonsoft.Json, System.IO.Compression.ZipFile

Code Example

using System;
using System.IO;
using System.IO.Compression;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public class SazReader
{
    public static List<Session> LoadSessions(string sazPath)
    {
        var sessions = new List<Session>();
        using var archive = ZipFile.OpenRead(sazPath);
        
        // Load manifest
        var manifestEntry = archive.GetEntry("SessionArchive.json");
        if (manifestEntry == null) throw new InvalidOperationException("Invalid SAZ: missing SessionArchive.json");
        
        using var manifestStream = manifestEntry.Open();
        using var reader = new StreamReader(manifestStream);
        var manifest = JObject.Parse(reader.ReadToEnd());
        
        foreach (JToken sessionToken in manifest["Sessions"])
        {
            var sessionId = sessionToken["Id"].ToString();
            var sessionDir = $"Raw/{sessionId.PadLeft(6, '0')}/";
            
            var session = new Session
            {
                Id = sessionId,
                Url = sessionToken["Url"]?.ToString(),
                StatusCode = (int?)sessionToken["StatusCode"] ?? 0,
                IsHttps = sessionToken["IsHTTPS"]?.ToObject<bool>() == true
            };
            
            // Read request body
            var reqBodyEntry = archive.GetEntry($"{sessionDir}requestbody.txt");
            if (reqBodyEntry != null)
            {
                using var reqBodyStream = reqBodyEntry.Open();
                using var reqBodyReader = new StreamReader(reqBodyStream);
                session.RequestBody = reqBodyReader.ReadToEnd();
            }
            
            sessions.Add(session);
        }
        return sessions;
    }
}

public class Session
{
    public string Id { get; set; }
    public string Url { get; set; }
    public int StatusCode { get; set; }
    public bool IsHttps { get; set; }
    public string RequestBody { get; set; }
}

Pro tip: Always validate IsHTTPS before assuming body content is plaintext — some HTTPS responses may still be base64-encoded if Fiddler couldn’t decrypt them (e.g., due to missing client cert or TLS version mismatch).

Parsing SAZ in Python (with Requests & zipfile)

Python offers lightweight alternatives for quick analysis or integration with pytest or Robot Framework. Use zipfile, json, and base64 — no external dependencies required beyond stdlib.

Minimal Working Script

import zipfile
import json
import base64
import os

def parse_saz(saz_path):
    sessions = []
    with zipfile.ZipFile(saz_path, 'r') as zf:
        # Load manifest
        with zf.open('SessionArchive.json') as f:
            manifest = json.load(f)
        
        for sess in manifest.get('Sessions', []):
            sess_id = sess['Id']
            raw_dir = f'Raw/{sess_id.zfill(6)}/'
            
            # Try reading request body
            req_body = b''
            try:
                with zf.open(f'{raw_dir}requestbody.txt') as f:
                    req_body = f.read()
                # Decode if base64-encoded (common for binary)
                if req_body.startswith(b'Base64:'):
                    req_body = base64.b64decode(req_body[7:])
            except KeyError:
                pass
            
            sessions.append({
                'id': sess_id,
                'url': sess.get('Url', ''),
                'status_code': sess.get('StatusCode', 0),
                'is_https': sess.get('IsHTTPS', False),
                'request_body': req_body.decode('utf-8', errors='replace'),
            })
    return sessions

# Usage
sessions = parse_saz('capture.saz')
for s in sessions[:3]:
    print(f"[{s['status_code']}] {s['url']} → {len(s['request_body'])} chars")

⚠️ Troubleshooting: If requestbody.txt is missing, check request.txt — sometimes bodies are embedded inline. Also verify Fiddler was configured to save request bodies: under Tools > Options > HTTP, ensure “Decrypt HTTPS traffic” and “Capture HTTPS CONNECTs” are enabled before capture, and “Save request/response bodies” is checked under File > Save > All Sessions.

Modifying & Rebuilding SAZ Archives

You can inject modified requests, annotate sessions, or even simulate failure scenarios by editing request.txt and regenerating the archive.

Steps to Inject a Modified Request

  1. Extract the SAZ using unzip capture.saz -d extracted/
  2. Edit extracted/Raw/000001/request.txt (e.g., change User-Agent or add X-Test-Flag: true)
  3. Update extracted/Raw/000001/session.json to reflect changes (e.g., bump X-Modified timestamp)
  4. Recompress: zip -r modified.saz extracted/
  5. Open modified.saz in Fiddler — it loads cleanly, and you can replay the edited request via Composer or AutoResponder.

🔧 Critical note on HTTPS decryption: If your original SAZ contained decrypted HTTPS responses, modifying request.txt won’t invalidate decryption — but replaying that session in a new Fiddler instance requires identical trust configuration. Ensure the target machine has Fiddler’s root certificate installed (Tools > Options > HTTPS > Actions > Export Root Certificate to Desktop) and “Decrypt HTTPS traffic” is enabled.

Automating SAZ Analysis with FiddlerCore

For deep integration — like filtering sessions by regex, calculating latency percentiles, or exporting to Prometheus metrics — use FiddlerCore’s native SessionArchive class.

Example: Filter and Export Failed HTTPS Sessions

var archive = SessionArchive.LoadFromFile(@"C:\temp\capture.saz");
var failedHttps = archive.Sessions
    .Where(s => s.IsHTTPS && s.responseCode >= 400)
    .Select(s => new {
        s.fullUrl,
        s.responseCode,
        s.oFlags["X-ElapsedTime-ms"]?.ToString() ?? "0"
    }).ToList();

File.WriteAllText(@"C:\temp\failed-https.json", JsonConvert.SerializeObject(failedHttps, Formatting.Indented));

This approach respects Fiddler’s internal parsing logic — including header normalization, charset detection, and response body decoding — making it more reliable than raw ZIP parsing for production tooling.

Common Pitfalls & How to Avoid Them

Issue Cause Fix
requestbody.txt missing “Save request bodies” disabled during capture Re-capture with Tools > Options > HTTP > Save request/response bodies enabled
Decrypted bodies appear garbled SAZ opened on machine without Fiddler root cert Install cert via Tools > Options > HTTPS > Actions > Trust Root Certificate
Replay fails with 400 Bad Request Modified request.txt lacks CRLF line endings Use \r\n, not \n, between headers and body
Session count mismatch Corrupted SessionArchive.json or missing Raw/ entries Validate ZIP integrity: zip -T capture.saz

Conclusion: Treat SAZ as Structured Data, Not Just Logs

The SAZ format is far more than a convenience archive — it’s a portable, extensible representation of full HTTP(S) transaction state. By mastering programmatic access, you shift from passive fiddler debugging to active pipeline integration: validating API contracts, detecting regressions in header behavior, stress-testing auth flows, or feeding network traces into ML-based anomaly detection.

Key takeaways:

  • SAZ is a ZIP + JSON + text — parseable without Fiddler, but richer with FiddlerCore.
  • HTTPS decryption context is not embedded — ensure target environments have certs and decryption enabled for accurate replay.
  • Always verify line endings, encoding, and base64 wrapping when editing manually.
  • Prefer SessionArchive.LoadFromFile() over raw ZIP parsing when building tooling inside .NET ecosystems.

Ready to go deeper? Explore our more tutorials for advanced fiddler proxy configurations, or dive into TLS inspection patterns with our browse Advanced Techniques tutorials. For custom SAZ automation needs, contact us — we build integrations for QA teams and security researchers daily.

Fiddler debugging isn’t just about watching traffic — it’s about transforming it into insight, automation, and reliability. Your next HTTP debugging breakthrough starts with understanding what’s inside that .saz file.

Share:

Related Topics

fiddler tutorialfiddler debugginghttp debuggingfiddler proxyhttps decryption

Get Fiddler Tips & Tutorials

Stay updated with the latest Fiddler tutorials, HTTP debugging guides, request modification tips, and web traffic analysis techniques.

Free forever. New tutorials published daily.

Related Articles