Ready to take Python coding to a new level? Explore our Python Code Generator. The perfect tool to get your code up and running in no time. Start now!
We all know the drill: you sit down to code, and twenty minutes later you're three levels deep in a Reddit thread about something you didn't even care about. Browser extensions exist, but they're easy to disable in a moment of weakness. What if you could block distracting websites at the operating system level — and automate it so the block kicks in during work hours and lifts when you clock out?
In this tutorial, we'll build a website blocker in Python that modifies your system's hosts file to redirect distracting sites to 127.0.0.1 (localhost). It works on Windows, macOS, and Linux, uses zero third-party libraries (pure Python standard library), and comes with block, unblock, and status commands. We'll also set up automated scheduling so it runs on its own — like a productivity firewall you set once and forget.
Before your computer asks a DNS server "hey, where is facebook.com?", it checks a local file called hosts. This file maps domain names to IP addresses and takes priority over any external DNS lookup. If you add this line:
127.0.0.1 facebook.com...then every request to facebook.com resolves to your own machine, where nothing serves the page. The browser spins for a moment and gives up. No sketchy extension, no dependency on willpower — just a one-line redirect at the OS level.
The hosts file lives at:
This entire project uses only Python's standard library — sys, platform, and pathlib are all built-in. No pip install required.
Create a file named website_blocker.py and let's build it step by step.
Start with the imports, the list of sites to block, and a helper that picks the correct hosts path for the current OS:
import sys import platform # ------------------------------------------------------------ # CONFIGURATION — edit this list to block different sites # ------------------------------------------------------------ SITES_TO_BLOCK = [ # Social media "www.facebook.com", "facebook.com", "www.twitter.com", "twitter.com", "www.instagram.com", "instagram.com", "www.reddit.com", "reddit.com", # Video / entertainment "www.youtube.com", "youtube.com", "www.tiktok.com", "tiktok.com", "www.twitch.tv", "twitch.tv", ] REDIRECT_IP = "127.0.0.1" # Markers keep our entries isolated so we never touch # other entries in the hosts file. START_MARKER = "# >>> WEBSITE BLOCKER START >>>" END_MARKER = "# <<< WEBSITE BLOCKER END <<<" # ------------------------------------------------------------ # Cross‑platform hosts path # ------------------------------------------------------------ def get_hosts_path(): """Return the absolute path to the hosts file for this OS.""" system = platform.system() if system == "Windows": return r"C:\Windows\System32\drivers\etc\hosts" # macOS and Linux both use /etc/hosts return "/etc/hosts" HOSTS_PATH = get_hosts_path()Each site gets two entries — one with www. and one without — because facebook.com and www.facebook.com are technically different hostnames and both need to be redirected.
The START_MARKER and END_MARKER are comment lines delimiters. They let us add and remove our entries without touching anything else in the hosts file — critical for safety.
A naive approach would be to just append lines to the end of the hosts file. But that creates problems:
By wrapping our entries between two comment markers, we have a clean "section" we can add, remove, or replace without ambiguity. After running the script, the bottom of your hosts file will look like this:
# >>> WEBSITE BLOCKER START >>> 127.0.0.1 www.facebook.com 127.0.0.1 facebook.com 127.0.0.1 www.twitter.com 127.0.0.1 twitter.com 127.0.0.1 www.instagram.com 127.0.0.1 instagram.com 127.0.0.1 www.reddit.com 127.0.0.1 reddit.com 127.0.0.1 www.youtube.com 127.0.0.1 youtube.com 127.0.0.1 www.tiktok.com 127.0.0.1 tiktok.com 127.0.0.1 www.twitch.tv 127.0.0.1 twitch.tv # <<< WEBSITE BLOCKER END <<<The block_websites() function reads the current hosts file, strips out any previous blocker section (so rerunning is safe), builds a fresh block with the current site list, and writes everything back:
def block_websites(): """Write (or refresh) the blocker block into the hosts file.""" # Read the current file with open(HOSTS_PATH, "r") as fh: content = fh.read() # Strip any previous block so we start fresh if START_MARKER in content: content = content.split(START_MARKER)[0].rstrip("\n") + "\n" # Build the block block_lines = [START_MARKER + "\n"] for site in SITES_TO_BLOCK: block_lines.append(f"{REDIRECT_IP}\t{site}\n") block_lines.append(END_MARKER + "\n") # Write everything back with open(HOSTS_PATH, "w") as fh: fh.write(content) fh.writelines(block_lines) unique_sites = len(SITES_TO_BLOCK) // 2 print(f"[+] Blocked {unique_sites} websites " f"({len(SITES_TO_BLOCK)} URLs) → {REDIRECT_IP}")Key details:
Unblocking is even simpler — just cut out everything between (and including) our two markers:
def unblock_websites(): """Remove the blocker block from the hosts file.""" with open(HOSTS_PATH, "r") as fh: content = fh.read() if START_MARKER not in content: print("[*] No websites are currently blocked.") return # Cut out the marked section before = content.split(START_MARKER)[0].rstrip("\n") after = content.split(END_MARKER)[-1] new_content = before + "\n" + after.lstrip("\n") with open(HOSTS_PATH, "w") as fh: fh.write(new_content) print("[+] All websites unblocked. Focus mode off.")The rstrip("\n") and lstrip("\n") calls prevent leftover blank lines from accumulating after repeated block/unblock cycles.
A quick status check shows you which sites are currently blocked and how many URLs are redirected:
def show_status(): """Print which websites are currently blocked.""" with open(HOSTS_PATH, "r") as fh: content = fh.read() if START_MARKER not in content: print("[*] No websites are currently blocked.") return block = content.split(START_MARKER)[1].split(END_MARKER)[0] sites = [line.strip() for line in block.split("\n") if line.strip() and not line.strip().startswith("#")] print(f"[*] {len(sites)} URLs currently blocked → {REDIRECT_IP}:") for site in sites: print(f" {site.split()[-1]}")Finally, wire everything to a simple command-line interface that dispatches on the first argument:
if __name__ == "__main__": if len(sys.argv) < 2: print("Website Blocker — block distracting sites via /etc/hosts\n") print("Usage:") print(" sudo python website_blocker.py block") print(" sudo python website_blocker.py unblock") print(" python website_blocker.py status") sys.exit(1) command = sys.argv[1].lower() if command == "block": block_websites() elif command == "unblock": unblock_websites() elif command == "status": show_status() else: print(f"[!] Unknown command: {command}") print("Valid commands: block, unblock, status") sys.exit(1)The hosts file is protected by the OS — editing it requires elevated privileges. Here's how to run the script on each platform:
Linux & macOS:
$ sudo python website_blocker.py block [+] Blocked 7 websites (14 URLs) → 127.0.0.1 $ python website_blocker.py status [*] 14 URLs currently blocked → 127.0.0.1: www.facebook.com facebook.com ... $ sudo python website_blocker.py unblock [+] All websites unblocked. Focus mode off.Windows:
Open Command Prompt or PowerShell as Administrator (right-click → Run as Administrator), then:
C:\> python website_blocker.py block [+] Blocked 7 websites (14 URLs) → 127.0.0.1The status command reads the file without writing, so it works without admin:
C:\> python website_blocker.py status [*] 14 URLs currently blocked → 127.0.0.1: www.facebook.com facebook.com ...The real power move is automation. Schedule the blocker to run at 9 AM (block distractions) and 6 PM (unblock) so it works on autopilot.
Edit your crontab:
$ sudo crontab -eAdd these two lines (adjust the path to your script):
# Block at 9:00 AM every weekday 0 9 * * 1-5 /usr/bin/python3 /home/you/website_blocker.py block # Unblock at 6:00 PM every weekday 0 18 * * 1-5 /usr/bin/python3 /home/you/website_blocker.py unblockSince crontab runs as root (via sudo crontab -e), no password prompt is needed — the script edits the hosts file silently in the background.
Create two scheduled tasks that run with highest privileges:
Repeat for the unblock task at 6 PM with argument unblock instead.
This tool is built to be extended. Here are a few directions:
You now have a clean, cross-platform website blocker that:
The full code is under 100 lines and every function does one thing well. Drop it on your machine, schedule it, and enjoy the extra focus.
Happy (productive) coding! ♥
Finished reading? Keep the learning going with our AI-powered Code Explainer. Try it now!
View Full Code Assist My CodingJoin 50,000+ Python Programmers & Enthusiasts like you!
Email address Subscribe This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.Ethical Hacking with Python EBook
Web Security with Python EBook
Cryptography with Python EBook
Practical Python PDF Processing EBook
Real-Time Traffic Monitoring System with YOLOv9 eBook
Mastering YOLO: Build an Automatic Number Plate Recognition System
© 2026 The Python Code. All rights reserved.
Got a coding query or need some guidance before you comment? Check out this Python Code Assistant for expert advice and handy tips. It's like having a coding tutor right in your fingertips!