Why You Should Build Your Own Website Monitoring Tool
I once missed a 3-million VND discount on an iPhone just because I was in a 15-minute meeting and couldn’t refresh the page. That’s when I realized that manually monitoring prices or news is exhausting and discouraging.
Tools like Distill.io or Visualping are great, but free versions usually limit you to under 30 checks per month. To check every 5 minutes, you might pay $15 – $25 monthly. With Python, you can build your own clone, customize ad filtering, and send Telegram messages completely for free.
Many people still use BeautifulSoup for scraping. However, for modern websites using React or Vue, BeautifulSoup often returns a blank HTML shell. That’s why I chose Playwright. This library simulates a real browser, waiting for JavaScript to render before fetching data, making it capable of handling the toughest websites today.
Environment Setup
First, ensure you have Python 3.8+ installed. We’ll need Playwright for web browsing and the requests library to connect with the Telegram API.
# Create a virtual environment to avoid library conflicts
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
# Install Playwright and requests
pip install playwright requests
# Download Chromium for Playwright (approx. 100-150MB)
playwright install chromium
For Telegram, chat with @BotFather, type /newbot to get your API Token. Don’t forget to send a message to the bot, then visit https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates to find your chat_id.
Detailed Implementation
Our script follows the pattern: Access -> Extract -> Compare -> Notify.
1. Fetching Data with Playwright
Instead of fetching the entire HTML, target a specific Selector (like a price class or title ID). This prevents the script from triggering false alerts due to timestamps or changing ad banners.
import asyncio
from playwright.async_api import async_playwright
async def get_website_content(url, selector):
async with async_playwright() as p:
# Run in headless mode (no browser window displayed)
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
# Simulate User-Agent to avoid anti-bot detection
await page.set_extra_http_headers({"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0"})
try:
await page.goto(url, wait_until="networkidle", timeout=60000)
await page.wait_for_selector(selector)
content = await page.inner_text(selector)
return content.strip()
except Exception as e:
print(f"Access error: {e}")
return None
finally:
await browser.close()
2. Checking for Content Changes
The simplest way to detect updates is to save the previous result in a .txt file. If the new content differs from the old, we update the file and trigger a notification.
import os
def has_changed(new_content, filename="last_state.txt"):
if not os.path.exists(filename):
with open(filename, "w", encoding="utf-8") as f:
f.write(new_content)
return False
with open(filename, "r", encoding="utf-8") as f:
old_content = f.read()
if new_content != old_content:
with open(filename, "w", encoding="utf-8") as f:
f.write(new_content)
return True
return False
3. Sending Messages via Telegram
With just a few lines of code using the requests library, you can push notifications directly to your phone.
import requests
def notify_telegram(message, token, chat_id):
url = f"https://api.telegram.org/bot{token}/sendMessage"
data = {"chat_id": chat_id, "text": message, "parse_mode": "HTML"}
return requests.post(url, data=data)
Putting It All Together
Here is the main function to run the entire process. Just replace the URL and Selector with real values to get started.
async def main():
CONFIG = {
"url": "https://tiki.vn/dien-thoai-iphone-15-pro-max-p251643444.html",
"selector": ".price-and-icon",
"token": "YOUR_TOKEN",
"chat_id": "YOUR_ID"
}
print("Checking website...")
current_data = await get_website_content(CONFIG["url"], CONFIG["selector"])
if current_data and has_changed(current_data):
msg = f"🚀 <b>New Update!</b>\nValue: {current_data}\nLink: {CONFIG['url']}"
notify_telegram(msg, CONFIG["token"], CONFIG["chat_id"])
print("Notification sent!")
else:
print("No changes found.")
if __name__ == "__main__":
asyncio.run(main())
Real-world Operating Experience
To keep your script running smoothly without getting your IP banned, keep these 3 points in mind:
- Check Frequency: Never check every 1-2 seconds. Major sites like Shopee or Amazon will block your IP instantly. A 15-30 minute cycle is usually ideal.
- Automation: Use
crontabif you have a VPS. Otherwise, leverage GitHub Actions to run your script 24/7 for free without needing your personal computer on. - Handling Dynamic Classes: Some sites change classes after every build. In these cases, use
xpathor stable attributes likedata-testidfor more accurate element targeting.
Building your own monitoring bot doesn’t just help you snag great deals. It’s also a fantastic way to practice understanding browser workflows and real-world data handling. Good luck!

