How the `{?}` Placeholder Enables Multiple Username Variant Checking in Sherlock

Sherlock expands a single search pattern into multiple concrete usernames by interpreting the special {?} placeholder as a variable separator that generates underscore, hyphen, and dot variants automatically.

The {?} placeholder is a core feature in the sherlock-project/sherlock repository that eliminates manual enumeration of username variations. When you provide a pattern like john{?}doe, the tool automatically probes for john_doe, john-doe, and john.doe across supported platforms, enhancing the discovery of accounts that use different naming conventions.

The Three-Step Variant Generation Process

Sherlock implements this capability through a coordinated three-step pipeline defined in sherlock_project/sherlock.py. Each step transforms the abstract pattern into concrete HTTP requests.

Step 1: Detecting the Placeholder with check_for_parameter

The process begins with check_for_parameter(username), which scans the input string for the presence of {?}. Located at lines 53-57 in sherlock_project/sherlock.py, this function returns True when the pattern requires expansion, triggering the variant generation logic.

from sherlock_project import sherlock

pattern = "john{?}doe"
if sherlock.check_for_parameter(pattern):
    print("Placeholder detected - generating variants")

Step 2: Generating Username Variants with multiple_usernames

When a placeholder is detected, multiple_usernames(username) (lines 62-68) replaces {?} with each character from the separator list ["_", "-", "."]. This produces a Python list containing every possible username combination.

variants = sherlock.multiple_usernames("john{?}doe")
print(variants)

# Output: ['john_doe', 'john-doe', 'john.doe']

Step 3: Interpolating URLs with interpolate_string

Finally, interpolate_string(input_object, username) (lines 43-50) inserts each generated variant into the site's URL template. This function replaces the generic {} token—defined in sherlock_project/sites.py (lines 27-31)—with the concrete username, preparing the final request URL.

site_url = "https://example.com/users/{}"
for username in variants:
    final_url = sherlock.interpolate_string(site_url, username)
    print(final_url)

# Output:

# https://example.com/users/john_doe

# https://example.com/users/john-doe

# https://example.com/users/john.doe

Complete Implementation Example

The main search loop coordinates these functions to dispatch separate HTTP requests for each variant. Here is the complete workflow demonstrating how Sherlock processes a single patterned query:

from sherlock_project import sherlock

# Define the pattern with the {?} placeholder

username_pattern = "john{?}doe"

# Check if expansion is needed

if sherlock.check_for_parameter(username_pattern):
    # Generate all three variants

    usernames = sherlock.multiple_usernames(username_pattern)
    
    # Template from sites.py manifest

    url_template = "https://example.com/profile/{}"
    
    # Probe each variant

    for username in usernames:
        target_url = sherlock.interpolate_string(url_template, username)
        # Sherlock sends individual HTTP requests for each URL

        print(f"Checking: {target_url}")

Key Source Files

Understanding the {?} placeholder requires familiarity with these specific files in the repository:

Summary

  • The {?} placeholder triggers automatic expansion of username patterns into multiple variants.
  • check_for_parameter() detects when expansion is required in sherlock_project/sherlock.py.
  • multiple_usernames() generates three separator variants: underscore, hyphen, and dot.
  • interpolate_string() binds each variant to site-specific URL templates containing the {} token.
  • This architecture allows Sherlock to discover accounts across platforms using different naming conventions without requiring users to manually enumerate each possibility.

Frequently Asked Questions

What characters does the {?} placeholder replace?

The {?} placeholder expands into three specific characters: the underscore (_), hyphen (-), and dot (.). These are hardcoded in the multiple_usernames() function within sherlock_project/sherlock.py, covering the most common username separator conventions across social platforms.

How does Sherlock handle multiple username variants during execution?

Sherlock treats each variant as a distinct query. After generating the list of usernames, the main search loop iterates through each variant and calls interpolate_string() to construct unique URLs, dispatching separate HTTP requests for every permutation. This ensures comprehensive coverage while maintaining the original search intent.

Can I use multiple {?} placeholders in a single username pattern?

The current implementation in sherlock_project/sherlock.py is designed to handle a single {?} occurrence per pattern. The multiple_usernames() function performs a straightforward replacement operation that would not generate combinatorial permutations for multiple placeholders.

Where is the URL template token {} defined?

The {} token used for final URL interpolation is defined in sherlock_project/sites.py at lines 27-31. This token serves as the insertion point where concrete usernames replace the generic placeholder after variant generation is complete.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →