DiffHook/Docs
PlatformTroubleshooting

Troubleshooting

Solutions to the most common issues.

I'm not receiving webhook deliveries

1. Check your logs first. Go to App → Logs. Find the relevant monitor and check the delivery status. If it shows failed, expand the entry to see the HTTP status code your endpoint returned.

2. Your endpoint returned a non-2xx status or timed out. DiffHook considers a delivery successful only when your endpoint returns 2xx within 10 seconds. Common causes:

  • Returning 500 due to an error in your handler
  • Slow processing before responding — move processing async and return 200 immediately
  • Firewall or WAF blocking DiffHook's IP range

3. Your endpoint URL is wrong. Re-check the webhook URL on the monitor. Ensure it is publicly reachable (not localhost).

4. All 3 retries failed. After 3 failed attempts, delivery stops. The entry in Logs shows failed. Fix your endpoint, then use Trigger now on the monitor to re-fire.


A monitor fired but I got no notification

Check that at least one notification channel is configured and connected:

  • App → Settings → Integrations — verify Slack/Discord/Telegram/Email is connected
  • Use the Test button to confirm the channel is working independently of monitor events

My monitor isn't detecting changes I can see on the page

JavaScript-rendered content. If the page loads content via JavaScript (React, Vue, SPAs), the static HTML fetched by DiffHook won't include it. Enable JS rendering on the monitor to use a headless browser.

CSS selector too narrow or broken. If you specified a cssSelector, verify it still matches an element on the page. Sites redesign — selectors can become stale. Remove the selector temporarily to confirm DiffHook sees the change at all, then refine.

Change is within the diff filter. DiffHook strips dynamic noise (timestamps, ad slots, session tokens). If your target content matches a filter pattern, it may be suppressed. Contact support with the URL and we can inspect the raw diff.

Polling jitter. Checks fire within a ±30 second window around the scheduled time. A change that appeared and disappeared within your polling interval will not be detected.


I'm getting too many false positive alerts

Use a CSS selector. Scope the monitor to only the content you care about:

{ "cssSelector": "#pricing-table" }

This filters out cookie banners, ad refreshes, timestamp changes, and other noise.

Increase the interval. If a page changes frequently but you only care about meaningful changes, a longer interval reduces noise.

Check for dynamic content. Some sites embed session tokens or nonces in the page body. These change on every load and will always trigger a diff. Use a CSS selector to exclude the affected element.


My monitor shows as paused unexpectedly

Monitors are paused automatically in two scenarios:

  1. Plan downgrade — You reduced your plan and have more active monitors than the new limit allows. Go to App → Monitors, resume the monitors you want to keep, and delete or pause the rest.
  2. Account suspended — A failed payment put your account on hold. Resolve the payment in App → Billing to reactivate.

A delivery was sent twice

Duplicate deliveries can happen in rare network failure scenarios (the request was delivered but the acknowledgement was lost, causing a retry). This is expected behavior.

Protect your handler with a deduplication key using monitor_id + triggered_at:

const key = `${body.monitor_id}:${body.triggered_at}`
if (await redis.get(key)) return
await redis.set(key, '1', 'EX', 86400)

See Best Practices for more on idempotency.


I can't verify the webhook signature

  • Make sure you're computing the HMAC over the raw request body bytes, not the parsed JSON
  • The signing secret is in App → Settings → API Keys
  • After rotating your secret, update your deployment before the old secret is revoked

See Verifying Signatures for full implementation examples.


Still stuck?

If none of the above resolves your issue, email support@diffhook.com with:

  • Your team ID (visible in the dashboard URL)
  • The monitor ID or URL
  • The log entry ID if a delivery failed
  • A description of the expected vs. actual behavior