| [ Web Proxy ] |
| Viewing: https://www.thepythoncode.com/article/build-website-blocker-python | [Back] [Original] |
Welcome! Meet our Python Code Assistant, your new coding buddy. Why wait? Start exploring 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:
/etc/hostsC:\Windows\System32\drivers\etc\hostsThis 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 <<<"
# ------------------------------------------------------------
# Crossplatform 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:
block twice duplicates every entry.unblock has no way to know which lines are ours.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:
if START_MARKER in content check means rerunning block won't duplicate entries it replaces the old block cleanly.\t between IP and hostname follows the hosts file convention and keeps things readable.len(SITES_TO_BLOCK) // 2 for the count because each domain has both a www and non-www entry.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.1
The 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 -e
Add 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 unblock
Since 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:
python (or full path like C:\Python311\python.exe)C:\Users\You\website_blocker.py blockRepeat for the unblock task at 6 PM with argument unblock instead.
This tool is built to be extended. Here are a few directions:
SITES_TO_BLOCK to an external config.json so you can edit the list without touching the script.ipconfig /flushdns after modifying the hosts file so changes take effect immediately without a restart.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! ♥
Just finished the article? Why not take your Python skills a notch higher with our Python Code Assistant? Check it out!
View Full Code Create Code for MeEthical 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.
| Web Proxy Viewer | New URL | Original Page |
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!