# How to Parse and Interpret Patator XML and CSV Output Formats

> Master Patator's XML CSV output and log directory structure. Learn to parse attack results efficiently with this technical guide.

- Repository: [lanjelot/patator](https://github.com/lanjelot/patator)
- Tags: how-to-guide
- Published: 2026-03-05

---

**Patator writes machine-readable attack results through `CSVFormatter` and `XMLFormatter` classes located in [`src/patator/patator.py`](https://github.com/lanjelot/patator/blob/main/src/patator/patator.py), storing them in a structured log directory created by `build_logdir` that includes runtime logs, result files, and individual response dumps.**

When conducting brute-force or fuzzing campaigns, analyzing results programmatically is critical for automation. The Patator framework provides native support for structured data export, enabling security engineers to integrate findings directly into parsing pipelines without manual log scraping.

## Where Patator's Output Formatters Are Implemented

Both output formatters inherit from Python’s `logging.Formatter` and are defined in the core engine file [`src/patator/patator.py`](https://github.com/lanjelot/patator/blob/main/src/patator/patator.py).

### CSVFormatter Class

The **CSVFormatter** resides at lines 86–100 in [`src/patator/patator.py`](https://github.com/lanjelot/patator/blob/main/src/patator/patator.py). This class formats each request result as a comma-separated line containing temporal data, log level, response indicators, and the tested candidate string.

### XMLFormatter Class

The **XMLFormatter** follows immediately at lines 102–123 in the same file. It serializes results into XML elements, providing identical data to the CSV format but with additional structural metadata including a `<target>` element containing the raw target string.

### The process_logs Entry Point

The `process_logs` function (lines 32–73) serves as the entry point for Patator’s logging subprocess. When you invoke Patator with `--csv` or `--xml` options, this function instantiates the appropriate formatter, checks for existing files to write headers only once, and attaches handlers to the logger.

## Understanding the Log Directory Structure

Patator constructs its output workspace through a dedicated directory builder that supports both manual and automatic path generation.

### How build_logdir Creates the Output Location

The `build_logdir` function (lines 890–899 in [`src/patator/patator.py`](https://github.com/lanjelot/patator/blob/main/src/patator/patator.py)) validates and prepares the logging directory. Called during `Controller.__init__`, it accepts the `--log-dir` (`-l`) path and handles directory creation with optional user confirmation via `--assume-yes`.

### Automatic Timestamped Directories with create_time_dir

When using the `-L SFX` flag, **Patator** invokes `create_time_dir` (lines 914–928) to generate a time-stamped subdirectory under `/tmp/patator`. The naming convention follows `YYYY-MM-DD/HHMMSS_<suffix>/`, preventing result collisions across multiple runs.

### Directory Contents and File Layout

A typical Patator log directory contains:

- **RUNTIME.log** – Raw command-line arguments and execution timestamps
- **RESULTS.csv** – CSV output (when `--csv` is specified)
- **RESULTS.xml** – XML output (when `--xml` is specified)
- **HITS** – Flat text file listing successful candidates (one per line)
- **Response dumps** – Raw HTTP/TCP responses saved as `<num>_<indicators>.txt` (e.g., [`001_200_532_0.450.txt`](https://github.com/lanjelot/patator/blob/main/001_200_532_0.450.txt))

The response dumps are written by `Logger.save_response` (lines 55–58), which embeds the iteration number and indicator values (status code, size, time) directly into filenames for immediate correlation with CSV or XML entries.

## Parsing Patator CSV Output Format

The CSV file includes a header row written by `process_logs` using the pattern `'time,level,%s\n' % ','.join(names)`, where `names` represents the dynamic indicator list. Standard columns include `time`, `level`, `code`, `size`, `time` (elapsed), `candidate`, `num` (iteration), and `mesg`.

```python
import csv
from pathlib import Path

csv_path = Path("/tmp/patator/2024-03-05/153012_ftp/RESULTS.csv")

with csv_path.open(newline="") as f:
    reader = csv.DictReader(f, delimiter=",")
    for row in reader:
        print(f"[{row['time']}] {row['candidate']}: {row['mesg']} (HTTP {row['code']})")

```

Use `csv.DictReader` to automatically map the header fields, allowing direct access to columns by name rather than index.

## Parsing Patator XML Output Format

The XML structure wraps all results in a `<root>` element. Each request generates a `<result>` tag with `time` and `level` attributes, plus child elements for each indicator and a `<target>` element containing connection details.

```python
import xml.etree.ElementTree as ET
from pathlib import Path

xml_path = Path("/tmp/patator/2024-03-05/153012_ftp/RESULTS.xml")
tree = ET.parse(xml_path)

for result in tree.getroot().findall("result"):
    candidate = result.findtext("candidate")
    code = result.findtext("code")
    mesg = result.findtext("mesg")
    
    # Access target attributes if needed

    target_elem = result.find("target")
    target_str = target_elem.text if target_elem is not None else "N/A"
    
    print(f"{candidate} -> {mesg} (code={code}, target={target_str})")

```

The XML format preserves the same data as CSV but structures multi-word messages unambiguously and includes the raw target string in the `<target>` element, useful for forensic reconstruction of complex pivot attacks.

## Practical Command-Line Examples

Generate both formats in an auto-managed directory:

```bash
patator http_fuzz url=FILE0 method=GET 0=urls.txt -L webscan --csv RESULTS.csv --xml RESULTS.xml

```

This creates `/tmp/patator/2024-XX-XX/XXXXXX_webscan/` containing both structured files plus the `HITS` file and response dumps.

Save only CSV to a specific location:

```bash
patator ssh_login host=10.0.0.1 user=FILE0 password=FILE1 0=users.txt 1=pass.txt -l /var/log/patator --csv scan.csv

```

Inspect successful candidates without parsing structured files:

```bash
cat /var/log/patator/HITS

```

## Summary

- **Patator XML and CSV output formats** are generated by `XMLFormatter` and `CSVFormatter` classes in [`src/patator/patator.py`](https://github.com/lanjelot/patator/blob/main/src/patator/patator.py), activated via `--xml` and `--csv` command-line switches.
- The **`process_logs` function** manages formatter initialization and header writing, appending results as the scan progresses.
- **`build_logdir`** and **`create_time_dir`** construct the output hierarchy, defaulting to `/tmp/patator` when using the `-L` flag.
- The log directory contains `RUNTIME.log`, result files, a `HITS` summary, and individual response dumps named with iteration numbers and indicator values.
- Parse CSV output using Python’s `csv.DictReader` and XML using `xml.etree.ElementTree` to extract candidate strings, response codes, and timing data for further analysis.

## Frequently Asked Questions

### What columns appear in Patator's CSV output?

Patator’s CSV includes the columns: `time`, `level`, `code`, `size`, `time` (response time in milliseconds), `candidate`, `num` (iteration number), and `mesg` (response message). The header is generated dynamically in `process_logs` based on the module’s indicator configuration.

### How does Patator name response dump files?

Response dumps follow the format `<num>_<code>_<size>_<time>.txt`, where `<num>` is the zero-padded iteration number and the remaining fields represent response indicators. These files are written by `Logger.save_response` in the log directory when logging is enabled.

### Can I generate both CSV and XML output simultaneously?

Yes. Patator accepts both `--csv FILE` and `--xml FILE` arguments in the same command. The `process_logs` function creates separate handlers and formatters for each, writing both formats concurrently to the specified log directory.

### Where does Patator store logs by default?

When using `-L <suffix>`, Patator stores logs in a timestamped subdirectory under `/tmp/patator`. When using `-l <dir>`, it stores them in the specified directory. If the directory does not exist, `build_logdir` creates it after user confirmation (unless `--assume-yes` is passed).