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:
sherlock_project/sherlock.py– Containscheck_for_parameter(),multiple_usernames(), andinterpolate_string(), implementing the core variant expansion logic.sherlock_project/sites.py– Defines the{}URL insertion token and site manifest structure (lines 27-31).tests/test_ux.py– Unit tests verifying placeholder detection and username generation accuracy.sherlock_project/__init__.py– Entry point integrating the variant checking into the CLI workflow.
Summary
- The
{?}placeholder triggers automatic expansion of username patterns into multiple variants. check_for_parameter()detects when expansion is required insherlock_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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →