A minimal Sherlock‑style tool in 45 minutes
Welcome to another official UVF IT guide! In this quick build you’ll create a tiny command‑line utility that checks a handful of social‑media sites for the existence of a given username, inspired by the Sherlock project.
We’ll use plain Python, the free requests library, and a tiny JSON file of sites – no paid APIs, no Docker, just what’s on your laptop.
pip to install requests. The real Sherlock supports 400+ sites; our clone checks only 5 for speed.Create a folder, a virtual environment, and add the site list file.
mkdir sherlock_clone && cd sherlock_clone
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install requests
cat > sites.json <<'EOF'
[
{"name": "Twitter", "url": "https://twitter.com/{}"},
{"name": "GitHub", "url": "https://github.com/{}"},
{"name": "Instagram", "url": "https://www.instagram.com/{}"},
{"name": "Reddit", "url": "https://www.reddit.com/user/{}"},
{"name": "Pinterest", "url": "https://www.pinterest.com/{}"}
]
EOFRead the JSON file into a Python list of dicts.
loader.py
import json
import pathlib
def load_sites(path: str = "sites.json") -> list[dict]:
"""Load the site definitions from a JSON file.
Returns a list of dictionaries with keys 'name' and 'url'."""
file_path = pathlib.Path(path)
if not file_path.is_file():
raise FileNotFoundError(f"Site list not found: {path}")
with file_path.open(encoding="utf-8") as f:
return json.load(f)
if __name__ == "__main__":
sites = load_sites()
print(f"Loaded {len(sites)} sites:")
for s in sites:
print(f"- {s['name']}: {s['url']}")In this step we turn the static site list into a working checker. The script reads *sites.json*, builds a URL for each service by inserting the target username, and makes a GET request. If the response returns HTTP 200 we consider the account existing and print a friendly [+] line; otherwise we stay silent. Keeping the logic simple makes it easy to extend later with concurrency or error handling.
sherlock_clone.py
import json, sys, requests
def load_sites(path='sites.json'):
with open(path, 'r') as f:
return json.load(f)
def check_username(username, sites):
for site in sites:
url = site['url'].replace('{username}', username)
try:
resp = requests.get(url, timeout=5)
if resp.status_code == 200:
print(f"[+] {site['name']}: {url}")
except requests.RequestException:
# network hiccup – just skip this site
continue
if __name__ == '__main__':
if len(sys.argv) != 2:
print('Usage: python sherlock_clone.py <username>')
sys.exit(1)
user = sys.argv[1]
sites_data = load_sites()
check_username(user, sites_data)Now that the checker is ready, we can try it against a real username. Activate your virtual environment, ensure *requests* is installed, and invoke the script with a sample handle. The output will list every service where the handle appears, each prefixed with [+] for quick scanning.
source venv/bin/activate
python sherlock_clone.py exampleuserAfter a successful run, verify that the console printed at least one [+] line (or none, which is also valid) and that no tracebacks appeared. To keep a permanent record, redirect the output to a file named after the searched username. You can now grow the tool by adding more entries to *sites.json* or by enhancing the script to write CSV/JSON logs.
python sherlock_clone.py exampleuser > exampleuser.txt| Check | Command / Why it matters |
|---|---|
Virtual environment activated and requests installed | source venv/bin/activate && pip list | grep requests |
| Running the script prints at least one [+] line or none without error | python sherlock_clone.py exampleuser |
| Output file created with same name as username | cat exampleuser.txt |
You now have a functional username‑search CLI. To approach the real Sherlock, expand sites.json to the full list, add concurrency with concurrent.futures, and implement CSV/JSON export options.