← All posts

Webhooks vs Polling for Monitoring: Which to Use and When

Quick answer: Use webhooks when the source you monitor can push events to you: they give near-instant notifications with almost no wasted requests. Use polling when the source cannot push, which covers most public web pages. Polling means you check on a schedule and compare results, trading some latency and load for the ability to watch anything.

Both approaches answer the same question, "did something change?", but they answer it in opposite directions. A webhook lets the source tell you. Polling means you ask, over and over. Picking the right one depends almost entirely on whether the thing you are watching offers to tell you at all.

The Core Difference

With webhooks, you register a URL with a service. When an event happens, that service sends an HTTP request to your URL with the details. You sit idle until something actually changes.

With polling, you run a job on a schedule (every minute, every hour) that fetches the current state and compares it to what you saw last time. You do the work whether or not anything changed.

Think of it as the difference between a doorbell and getting up to check the front door every five minutes. The doorbell is better when it exists. Not every door has one.

The Tradeoffs

Factor Webhooks Polling
Latency Near-instant As slow as your interval
Wasted requests Almost none Many (most checks find no change)
Who does the work The source You
Setup complexity You need a public endpoint You need a scheduler
Works on any source No, source must support it Yes, anything you can fetch
Reliability risk Missed/duplicate deliveries Missed changes between polls
Control over timing None, events arrive when they arrive Full, you set the cadence

Latency

Webhooks win on speed. The event reaches you within seconds of happening. Polling can only detect a change on the next scheduled check, so your worst-case latency equals your interval. Poll every hour and a change can sit unnoticed for 59 minutes.

Load and cost

Polling is wasteful by design. If a page changes once a week and you poll it every five minutes, roughly 2,000 of your 2,016 weekly checks find nothing. Webhooks flip this: you only get traffic when there is something to report. If you pay per request, this matters.

Complexity and reliability

Webhooks move complexity to the receiving side. You need a public HTTPS endpoint that is always up, you have to verify the payload is genuine (signatures), and you have to handle retries and duplicate deliveries because networks fail. Miss a delivery during downtime and the event may be gone.

Polling is simpler to reason about. A cron job and a comparison. Its failure mode is different: if something changes and then changes back between two polls, you never see it. For most monitoring that is acceptable; for auditing every state transition it is not.

When Each One Fits

Reach for webhooks when:

  • The source explicitly supports them (payment processors, GitHub, Stripe, most SaaS platforms).
  • You need changes reflected in seconds.
  • The event volume is low relative to how often you would otherwise poll.

Reach for polling when:

  • You are monitoring a public web page, a competitor's site, a product listing, or anything that has no notification system. This is the common case.
  • You want full control over timing and rate.
  • The source is untrusted or third-party and you cannot ask it to call you.

Most web monitoring lands in the polling column simply because arbitrary websites do not offer to notify you when their content changes.

Building a Polling Monitor When No Webhook Exists

Here is the honest reality: the page you want to watch almost certainly has no webhook. So you build a small poller. The pattern is always the same:

  1. Fetch the current content.
  2. Reduce it to a stable representation (the text you care about, or a hash).
  3. Compare against the last stored value.
  4. If it differs, notify and store the new value.

Fetching raw HTML and diffing it directly is fragile, because timestamps, ads, and session tokens change on every load and trigger false alarms. Fetching clean content instead removes most of that noise. Here is a poller using link.sc to get stable markdown:

import hashlib
import json
import os
import requests

API_KEY = os.environ["LINKSC_API_KEY"]
URL = "https://example.com/pricing"
STATE_FILE = "last_seen.json"

def fetch_content(url):
    resp = requests.post(
        "https://api.link.sc/v1/fetch",
        headers={"x-api-key": API_KEY},
        json={"url": url, "format": "markdown"},
    )
    resp.raise_for_status()
    return resp.json()["content"]

def load_last_hash():
    if os.path.exists(STATE_FILE):
        with open(STATE_FILE) as f:
            return json.load(f).get("hash")
    return None

def save_hash(h):
    with open(STATE_FILE, "w") as f:
        json.dump({"hash": h}, f)

def check():
    content = fetch_content(URL)
    current = hashlib.sha256(content.encode()).hexdigest()
    if current != load_last_hash():
        print(f"Change detected on {URL}")
        # send your alert here: email, Slack, etc.
        save_hash(current)
    else:
        print("No change.")

if __name__ == "__main__":
    check()

Run it on a schedule. On Linux, cron every 30 minutes:

# crontab -e
*/30 * * * * /usr/bin/python3 /home/you/monitor.py >> /home/you/monitor.log 2>&1

Getting clean markdown instead of raw HTML is what makes the hash comparison reliable, because you are diffing the meaningful content and not the page's churn. For the full pattern, including how to diff specific sections and cut down on noise, see our guide on how to monitor web page changes and get alerts.

Tuning the Poll Interval

The interval is the one knob that matters. Set it by how fast you need to know versus how much load and cost you can accept.

  • Fast-moving, high stakes (a price you actively trade on): minutes.
  • Normal business monitoring (competitor pages, docs, status): every 15 to 60 minutes.
  • Slow content (terms of service, policy pages): daily.

Do not poll faster than you can act on the result. If nobody looks at the alert for hours, a one-minute interval just burns credits. Respect the site too: hammering a server every few seconds is rude and can get you blocked. If you are watching prices specifically, our post on monitoring competitor pricing changes covers sensible cadences.

A Hybrid Worth Knowing

You do not always have to choose. A common real-world setup polls a source on a relaxed schedule, then exposes its own webhook to downstream consumers. Your poller absorbs the "no notification available" problem, and everything downstream of you gets clean, push-style events. You take the polling cost once so the rest of your system behaves like it has webhooks.

The Bottom Line

If the source can push, use webhooks. They are faster and cheaper per event. If it cannot, and most of the open web cannot, poll on a sensible interval against clean content and you will catch what matters without drowning in false positives. The reliability of a poller comes down to what you compare, so fetch stable content, hash the part you care about, and let the schedule do the rest.


Want to build a monitor without wrestling raw HTML? Start free on link.sc with 500 credits a month and fetch clean, diff-friendly content from any page.