# How Maigret Generates Username Permutations and Variants: Inside the Permutation Engine

> Discover how Maigret generates username permutations and variants using its Permute class. Learn about its approach to combinatorial permutations and visual variations.

- Repository: [Soxoj/maigret](https://github.com/soxoj/maigret)
- Tags: internals
- Published: 2026-04-30

---

**Maigret expands a supplied list of usernames by generating every combinatorial permutation and visual variant using the `Permute` class in [`maigret/permutator.py`](https://github.com/soxoj/maigret/blob/main/maigret/permutator.py), applying separators like underscores, hyphens, and periods, and optionally padding with leading or trailing underscores to capture common handle variations.**

Maigret, the open-source username investigation tool, systematically expands search coverage by generating username permutations and variants that targets might use across different platforms. The core logic resides in the `Permute` class within [`maigret/permutator.py`](https://github.com/soxoj/maigret/blob/main/maigret/permutator.py) (lines 5-26), which creates combinatorial variations when activated via the command-line interface. This capability allows investigators to discover accounts where users combine multiple identifiers or modify their base handles with common separators.

## The Permutation Engine Architecture

The permutation system centers on the **`Permute`** class located in [`maigret/permutator.py`](https://github.com/soxoj/maigret/blob/main/maigret/permutator.py). This compact implementation systematically generates variants through combinatorial logic, processing input usernames according to specific delimiter rules and padding patterns.

### Core Separators and Input Format

The engine applies four distinct **separators** to combine username elements: an empty string (`""`), an underscore (`"_"`), a hyphen (`"-"`), and a period (`"."`). The class receives input as a Python dictionary mapping usernames to their identifier types, formatted as `{username: id_type}` where the value represents the credential classification (typically `"username"`).

### Generation Rules and Combinatorial Logic

The `gather()` method implements three primary generation strategies across approximately thirty lines of code:

- **Single-Element Processing**: When operating in `"all"` mode with a single input username, the engine emits the original name plus variants with leading and trailing underscores (e.g., `alice`, `_alice`, `alice_`).

- **Multi-Element Permutations**: For inputs containing multiple usernames, the algorithm iterates through subset sizes from 1 to N, generating every possible ordering using `itertools.permutations`. Each ordering is concatenated with each of the four separators to produce candidate handles like `alice_bob`, `bob-alice`, or `alice.bob`.

- **Underscore Padding**: When the empty separator joins elements (creating glued variants like `alicebob`), Maigret additionally generates underscore-padded versions including `_alicebob` and `alicebob_` to capture common social media handle patterns.

## CLI Integration and Activation Workflow

The permutation feature integrates directly into Maigret's command-line workflow in [`maigret/maigret.py`](https://github.com/soxoj/maigret/blob/main/maigret/maigret.py) (lines 58-62). Activation requires specific conditions to prevent invalid permutations of email addresses or phone numbers.

When the **`--permute`** flag is present, the CLI validates the input before invoking the engine:

```python

# maigret/maigret.py – lines 58-62

usernames = {u: args.id_type for u in args.username
             if u and u not in ['-'] and u not in args.ignore_ids_list}
if args.permute and len(usernames) > 1 and args.id_type == 'username':
    original_usernames = " ".join(usernames.keys())
    usernames = Permute(usernames).gather(method='strict')

```

The permutation step executes only when **more than one username** is supplied and the identifier type equals `"username"`. The `method='strict'` parameter generates combined forms exclusively, excluding solitary usernames from the output. The resulting dictionary, now enriched with permuted variants, drives the subsequent site-checking phase where Maigret queries each supported service for every generated handle.

## Strict vs All Mode Comparison

Maigret supports two distinct permutation modes that control the breadth of generated variants:

- **Strict Mode**: Generates only combined forms (multi-element permutations) plus underscore-padded glued variants. For inputs `alice` and `bob`, this produces `alice_bob`, `bob_alice`, `alice-bob`, `bob-alice`, `alice.bob`, `bob.alice`, `alicebob`, `bobalice`, `_alicebob`, `alicebob_`, `_bobalice`, and `bobalice_`. This mode excludes solitary usernames.

- **All Mode**: Includes all strict mode variants plus the original single usernames with optional leading and trailing underscores. This adds `alice`, `_alice`, `alice_`, `bob`, `_bob`, and `bob_` to the strict output.

The expected behavior for both modes is verified by the test suite in [`tests/test_permutator.py`](https://github.com/soxoj/maigret/blob/main/tests/test_permutator.py) (lines 5-50).

## Practical Implementation Examples

### Command-Line Usage

Invoke the permutation engine using the `--permute` flag with multiple usernames:

```bash

# Generate permutations for two usernames

maigret -u alice bob --permute

```

This command probes sites for the strict mode variants including `alice_bob`, `bob_alice`, `alice-bob`, `bob-alice`, `alice.bob`, `bob.alice`, `alicebob`, `bobalice`, `_alicebob`, `alicebob_`, `_bobalice`, and `bobalice_`.

### Python API Integration

Programmatically generate variants by importing the `Permute` class:

```python
from maigret.permutator import Permute

# Define original usernames with identifier type

names = {"alice": "username", "bob": "username"}

# Generate strict mode variants (default for CLI)

strict_variants = Permute(names).gather(method="strict")
print(strict_variants.keys())

# Output: dict_keys(['alice_bob', 'bob_alice', 'alice-bob', 'bob-alice',

#            'alice.bob', 'bob.alice', 'alicebob', 'bobalice',

#            '_alicebob', 'alicebob_', '_bobalice', 'bobalice_'])

# Generate all mode variants including single names

all_variants = Permute(names).gather(method="all")
print(all_variants.keys())

# Includes strict variants plus: 'alice', '_alice', 'alice_', 

# 'bob', '_bob', 'bob_'

```

## Summary

- Maigret generates username permutations and variants through the **`Permute`** class in [`maigret/permutator.py`](https://github.com/soxoj/maigret/blob/main/maigret/permutator.py), utilizing four separators (empty, underscore, hyphen, period) to combine input elements.
- The permutation engine activates via the **`--permute`** CLI flag only when multiple usernames are provided with the identifier type set to `"username"`, as implemented in [`maigret/maigret.py`](https://github.com/soxoj/maigret/blob/main/maigret/maigret.py) (lines 58-62).
- **Strict mode** produces only combined username forms and underscore-padded glued variants, while **all mode** additionally includes solitary usernames with leading and trailing underscores.
- The implementation leverages `itertools.permutations` to generate every possible ordering of input elements, systematically covering the combinatorial space required for comprehensive username discovery across social platforms.

## Frequently Asked Questions

### What separators does Maigret use when generating username variants?

Maigret uses four separator characters defined in the `Permute` class: an empty string (for glued variants), an underscore (`_`), a hyphen (`-`), and a period (`.`). Each separator is applied to every permutation of input usernames to generate distinct variant combinations.

### When does Maigret automatically activate the permutation feature?

The permutation feature activates automatically when the user supplies the `--permute` command-line flag, provides **more than one username**, and sets the identifier type to `"username"`. The logic explicitly checks `len(usernames) > 1 and args.id_type == 'username'` in [`maigret/maigret.py`](https://github.com/soxoj/maigret/blob/main/maigret/maigret.py) to prevent permuting non-username identifiers like email addresses or phone numbers.

### What is the difference between strict and all permutation modes?

**Strict mode** generates only combined forms of multiple usernames (e.g., `alice_bob`, `bob-alice`) and underscore-padded glued variants (e.g., `_alicebob`), excluding solitary usernames. **All mode** includes these strict variants plus the original individual usernames with optional leading and trailing underscores (e.g., `alice`, `_alice`, `alice_`).

### Which source files contain the username permutation logic?

The core permutation logic resides in **[`maigret/permutator.py`](https://github.com/soxoj/maigret/blob/main/maigret/permutator.py)**, which implements the `Permute` class and its `gather()` method. The CLI integration and activation conditions are handled in **[`maigret/maigret.py`](https://github.com/soxoj/maigret/blob/main/maigret/maigret.py)** (lines 58-62). Unit tests validating the expected output for both modes are located in **[`tests/test_permutator.py`](https://github.com/soxoj/maigret/blob/main/tests/test_permutator.py)** (lines 5-50).