Website Monitoring
Watch any URL — a marketing site, a REST API, a health endpoint — and get told when it goes down, returns the wrong thing, gets slow, or lets its TLS certificate expire.
What is a website monitor?
A website monitor makes an HTTP request to one URL on a schedule and reports whether the response was what you expected. "What you expected" is yours to define: a status code, some text in the body, a value at a JSON path, a response header, a size range — or just "it answered at all".
Example: "https://api.example.com/health should return 200 with "status":"ok" in the body, within 30 seconds, every minute. Page me if it doesn't."
It is the monitor most people mean when they say "uptime monitoring", and it is the one that carries the most extra machinery: the same check also watches your TLS certificate, can grade your security headers, can scan your domain against malware databases, can tell you when the page content changes, and can alert you when your slowest 5% of responses get slower.
When to use one
- Public websites. Your homepage, docs, marketing pages, customer portals — anything a browser loads over HTTP.
- APIs and health endpoints. A
/health,/readyzor/api/statusendpoint, with a JSON assertion so you're checking the answer, not just the status line. - TLS certificate expiry. Any HTTPS URL gets certificate monitoring automatically. You don't have to set up anything separate.
- Third-party dependencies. The payment provider, the auth provider, the CDN you'd want to know about before your customers tell you.
- Post-deploy verification. Point a monitor at a version endpoint with a keyword assertion, and a bad deploy announces itself.
When to use something else
| You want to know | Use this instead |
|---|---|
| "Can a user actually log in and check out?" | Browser monitor — drives a real Chromium session through a multi-step flow. A website monitor fetches one URL; it cannot click, type, or run your JavaScript. |
| "Does this multi-step API workflow still work end to end?" | API flow monitor — log in, extract a token, call the protected endpoint, assert per step. |
| "Is this host reachable at all?" | Ping monitor — an ICMP echo, no HTTP involved. Useful for separating "the box is gone" from "the web server is gone". |
| "Is this non-HTTP service listening?" | Port monitor — Postgres, SMTP, SSH, a broker. |
| "Do my DNS records still say what I expect?" | DNS monitor — a website monitor tells you the site loaded; it doesn't tell you your A record was rewritten and now points somewhere that also loads. |
| "Did my nightly cron job run?" | Cron job monitor — an inbound heartbeat, not an outbound check. See Jobs Overview. |
How it works
Every check, Enori:
- Resolves your hostname and confirms it points to a publicly routable address.
- Opens the connection and, for HTTPS, completes the TLS handshake — recording DNS, connect, TLS, time-to-first-byte and download timings separately.
- Sends your request (method, body, authentication, custom User-Agent) and follows redirects if you allow them.
- Evaluates every assertion you configured against the response.
- Records the result, and — on a slower cadence — refreshes the certificate details, the security-header grade and the reputation scan.
What counts as Up, Degraded, and Down
This distinction matters, because the two failure kinds mean very different things and Enori treats them differently.
Up — every assertion you configured passed.
Degraded — the site answered, but your content assertion didn't match. The origin is reachable and serving; something about the response is wrong. These are the four:
| Reason | What happened |
|---|---|
| Expected keyword not found | Your keyword assertion didn't hold. In the default Contains mode that means the text was missing; in Does not contain mode it means the text was there when it shouldn't be. Either way the check tells you which, in words. |
| JSON validation failed | The JSON path was missing, or its value didn't match what you expected. |
| Expected response header not found | Your expected response header wasn't present. |
| Response header value mismatch | The header was there, with a different value. |
Down — the request failed, or the response was structurally wrong. Among the reasons you'll actually see:
| Reason | What happened |
|---|---|
| Unexpected HTTP status | The status code didn't match what you asked for. The message names what was actually asserted — "Expected status 200, got 503". See the note on Expected Status below; this is the single most common surprise. |
| Timed out | No response within your timeout. |
| Connection refused | Nothing accepted the connection. |
| Response size out of range | The body was smaller or larger than the bounds you set — a truncated or blank page. |
| Too many redirects | The redirect chain exceeded 10 hops. |
| DNS resolution failed | The hostname didn't resolve. |
| Blocked target | The hostname resolves to a private, internal or reserved address. Enori only monitors publicly reachable hosts — including after a redirect. |
Why the split: a Degraded result never triggers cross-region verification, because another region checking availability would just confirm the site is up and quietly suppress a real content problem. A Down result does get verified — see Where checks run below.
How often
You choose the interval when you create the monitor. Options run from 1 minute to 24 hours, defaulting to 5 minutes. A 30-second interval is available as an add-on; every plan's floor without it is 60 seconds.
One exception worth knowing: while a monitor is Down, Enori re-checks it every 30 seconds regardless of your configured interval, so recovery is detected quickly. It returns to your normal interval once it's back Up.
Where checks run from
Each monitor has a primary region — the location its regular checks run from. You can also let Enori pick the closest region from your URL ("Automatic").
When a check fails, Enori doesn't page you on one region's opinion. Other regions re-check the same URL first, and only a confirmed failure becomes an alert. While that's happening the monitor shows an amber Verifying pill instead of a red dot.
| Plan | Multi-region verification |
|---|---|
| Base | Always on. Not configurable — the false-positive guard is baseline on every plan. |
| Pro | On by default; you can turn it off per monitor. |
| Business | On by default, and you can name exactly which regions do the verifying (leave empty to auto-select). |
Verification applies to Down (availability) only, never to Degraded content assertions.
If your site sits behind a firewall, WAF, or bot-protection rule, see Monitoring IP Addresses for allowlisting.
Setting one up
The create flow is two steps. Everything below is on one screen in step 2 — it's long because this monitor type does a lot, but only two fields are actually required.
Step 1 — Type
Click Create Monitor, then pick Website & API (labelled HTTP check in the step header). It's the default selection. Click Continue.
Screenshot: the monitor type picker with the Website tile selected.
Step 2 — Configure
The two required fields
| Field | What to enter |
|---|---|
| Monitor Name \* | Anything you'll recognise in an alert at 3am. e.g. "Production API — health". |
| URL \* | The full URL to check, e.g. https://api.example.com/health. If you leave off the scheme, Enori prepends https:// when you tab out of the field. |
Only http:// and https:// are accepted. If the URL is https://, you'll see a confirmation that SSL certificate monitoring is on — that's automatic, there's nothing to enable.
Group (optional) lets you file the monitor under a heading on the monitors list. Pick an existing group or create a new one.
Screenshot: step 2 of the wizard showing Monitor Name, Group and URL.
Advanced Options
This section is expanded by default. Every field in it has a working default, so you can ignore all of it for a basic uptime check.
Request
| Field | Default | Notes |
|---|---|---|
| HTTP Method | GET | GET, POST, PUT, DELETE, HEAD, OPTIONS, PATCH. |
| Expected Status | 200 | One exact code. See the warning below, and Accepting more than one status code if you need a set. |
| Min Size (bytes) | (none) | Optional floor on the response body. Catches blank or truncated pages. |
| Max Size (bytes) | (none) | Optional ceiling. Must be ≥ the minimum if you set both. |
| Request Body | (none) | Only shown for POST, PUT and PATCH. Sent with every check. |
| Timeout (seconds) | 30 | 5 to 120 seconds. |
| Follow Redirects | on | Follows 3xx responses, up to 10 hops. |
⚠️ Expected Status is an exact match, and it defaults to 200. If your endpoint legitimately answers
201,204or301, put that number in the field — otherwise every check reports Down — unexpected HTTP status. This is the most common misconfiguration on this monitor type.
If you set Min Size or Max Size and the response has no measurable size, the assertion is skipped rather than failed — an unknown size never causes a false Down.
Authentication
For password-protected pages and token-gated APIs.
| Option | What you enter |
|---|---|
| None (default) | — |
| Basic (username + password) | Username and password. |
| Bearer token | The token value. |
The secret is encrypted at rest and never shown again. When you later edit the monitor, leave the secret field blank to keep the stored value, or type a new one to replace it.
Response Validation
Three independent, optional assertions. Enable any combination; leave a field empty to skip that check. All three produce Degraded, not Down, when they fail.
| Field | What it does |
|---|---|
| Keyword + Keyword match | Looks for text in the response body. The Keyword match dropdown next to it decides how — see below. |
| JSON path + Expected value | Reads a value out of a JSON response. Path must start with $. — e.g. $.data.status. Leave the value empty to just assert the path exists. |
| Response header + Expected value | Asserts a response header. Header name is case-insensitive — e.g. X-Cache. Leave the value empty to just assert the header is present. |
Setting an expected value without its path or header name is rejected — the value has nothing to match against.
Keyword match modes. Leave Keyword empty and no keyword check runs at all; the dropdown is then irrelevant. Fill it in and pick one of four modes:
| Mode | What passes | What fails |
|---|---|---|
| Contains — the text must be present (default) | The text appears anywhere in the body, ignoring letter case. | The text goes missing. |
| Contains (case-sensitive) — letter case must match | Same, but exact case. OK does not match ok. | The text goes missing, or only differs by case. |
| Does not contain — alert when the text appears | The text is absent. | The text shows up. Ignores letter case. |
| Regex — the body must match a pattern | The body matches your regular expression. | It doesn't match — or the pattern is invalid or too slow. |
Does not contain is the one most people are looking for. It's the inverse assertion: the check fails because the text appeared. Use it for error text that a broken page still serves with a perfectly healthy 200:
"Alert me when https://shop.example.com starts containing Database error."
Set Keyword to Database error and Keyword match to Does not contain. While the page is clean the monitor is Up; the moment that string appears anywhere in the HTML it goes Degraded, with the reason "Forbidden keyword 'Database error' was found in response body". Common targets: Exception, Fatal error, Under maintenance, 502 Bad Gateway, a stack-trace marker.
Regex mode, specifically:
- The pattern is a .NET regular expression, matched case-insensitively — you don't need
(?i). - Each evaluation is capped at 1 second. A pattern that backtracks catastrophically against a large page (the classic
(a+)+bshape) fails the check rather than tying up the checker — you get "Keyword regex '…' timed out after 1s against response body". - An invalid pattern is not caught when you save it. The monitor saves fine, then every check fails with "Invalid keyword regex '…': <reason>" until you fix it. If you use regex mode, hit Check Now straight after saving to confirm the pattern actually compiles.
JSON path syntax. Supported: dot notation ($.data.items[0].status), array index including negative ($.items[-1]), and the wildcard ($.items[*].status). Not supported: recursive descent (..) and filter expressions ([?()]).
Header value matching uses contains, not equals — so an expected value of application/json matches an actual application/json; charset=utf-8.
Screenshot: the Response Validation block with a keyword filled in, the Keyword match dropdown open showing all four modes, and a JSON path below it.
Detect content changes
Off by default. When on, Enori fingerprints the page each check and alerts you when the content changes.
- CSS Selector (optional) — monitor only part of the page, e.g.
#pricing-tableor.main-content. Leave empty to watch the whole page. - Timestamps, session IDs and CSRF tokens are stripped automatically, so normal page churn doesn't fire alerts.
- The first check after you enable it establishes the baseline; it doesn't alert.
- Notification frequency is throttled by a cooldown — 30 minutes by default, adjustable from 0 to 1440 minutes when you edit the monitor. Detection still runs every check; only the notification is throttled.
Reputation scanning
Off by default. Checks your URL against Google WebRisk and URLhaus malware databases, refreshed roughly every 6 hours. You get an alert when the URL becomes flagged, and another when it clears. Useful if you host user-generated content, or if being silently blocklisted would be expensive.
Security header monitoring
Off by default. Grades the security headers your site sends, roughly every 12 hours.
Six headers are scored, weighted by risk, out of 100:
| Header | Points |
|---|---|
Content-Security-Policy | 25 |
Strict-Transport-Security | 20 |
X-Frame-Options | 15 |
X-Content-Type-Options | 15 |
Referrer-Policy | 15 |
Permissions-Policy | 10 |
| Grade | Score |
|---|---|
| A+ | 90–100 |
| A | 80–89 |
| B | 60–79 |
| C | 40–59 |
| D | 20–39 |
| F | below 20 |
Most sites grade F to begin with. Apache and nginx ship no security headers by default, and sites on shared hosting or off-the-shelf site builders almost never have them configured. That's not a bug in the grade.
Because of that, there are two alert modes:
| Mode | Behaviour | Use when |
|---|---|---|
| Baseline (default, recommended) | Silently captures your current grade the first time it checks, then alerts only when the grade drops below that baseline. Recovers when it returns. | Almost always. You want to know about a regression, not be reminded daily about a known state. |
| Absolute | Alerts on every check where the grade is below a threshold you choose — A+, A, B, C (default) or D. | Compliance evidence collection (SOC 2, ISO 27001) where you want a record every time. |
If you later fix your headers and want future regressions measured against the new, better grade, reset the baseline from the Security Headers card on the monitor's detail page.
Primary Region
Pick where regular checks run from: Automatic (chosen from your URL), West Europe (Falkenstein), North Europe (Helsinki), East US (Ashburn), West US (Hillsboro), or Southeast Asia (Singapore). Regions whose probes aren't live yet show as Coming soon and can't be selected.
Below it, Multi-region verification — always on and non-configurable on Base, a toggle on Pro, and a toggle plus a verifier-region picker on Business. See Where checks run from.
Screenshot: the Primary Region radio list with the multi-region verification panel below it.
Check Interval
5 minutes by default. Choose from 1, 2, 5, 10, 15, 30 minutes, or 1, 2, 4, 6, 12, 24 hours. 30 seconds appears in the list marked (add-on required) unless you have the add-on.
Alerts
Still step 2, below the divider.
When to alert — how many consecutive failed checks before Enori tells you:
| Option | What it means |
|---|---|
| First failure | Alert as soon as one check fails. |
| 2 consecutive failures (default) | Waits for a second failure — skips brief hiccups like a one-off 502 during a deploy. |
| 3 consecutive failures | Only alert after three in a row. |
| 5 consecutive failures | Only alert when it's clearly, persistently down. |
Notify me via — tick the alert channels this monitor should use. If you have an email channel and haven't picked anything, Enori selects it for you. No channels yet? There's a link straight to the channel setup. See Alerts.
Repeat Alerts — whether to keep reminding you while the monitor stays down. Default is Don't repeat: one alert when it goes down, one when it recovers, nothing in between. You can instead repeat every 1, 2, 3, 5 or 10 checks.
Alert on slow response — off by default. When on:
- P95 Threshold (ms) — 100 to 30,000. Typical: 200–500 ms for APIs, 1–3 s for websites.
- Check count — the rolling window the P95 is computed over: last 10, 20 (default), 50 or 100 checks.
It fires once the rolling window's P95 exceeds the threshold. The recovery alert waits for 3 consecutive checks back under the threshold, so a single fast response doesn't declare victory, and re-alerts are suppressed for 5 minutes afterwards to prevent flapping.
Escalation Policy (optional, collapsed) — pick a policy so unacknowledged alerts escalate to more people. See Alerts.
Click Create Monitor.
The monitor starts with status Unknown and its first check is scheduled at a random point inside the first interval — so a 5-minute monitor runs its first check somewhere in the next 0–5 minutes. That stagger is deliberate: it stops every monitor created in the same session from firing in lockstep forever after. If you want a result right now, hit Check Now on the monitor.
After you create it — settings the wizard doesn't cover
A few settings don't appear in the create wizard. Most live on the monitor itself — open it and click Edit, or use the cards on its detail page:
| Setting | Where | Notes |
|---|---|---|
| Custom request headers | Edit → Request Headers | Not in the create wizard — create the monitor first, then add them. See below. |
| SSL expiry warning threshold | SSL card on the detail page | 7, 14, 30 (default) or 60 days before expiry. |
| Custom User-Agent | Edit → Advanced | Max 512 characters, no line breaks. The default is already browser-like and passes most WAFs; override it when a bot-protection product is blocking checks. |
| Content-change alert cooldown | Edit, or Alert Settings | 0–1440 minutes, default 30. |
| Tags | Edit | For filtering the monitors list. |
| Alert when down / Alert when recovered | Edit → Alert Settings | Both on by default. |
Custom request headers
Some endpoints need a header before they'll answer properly — an API version, a tenant id, a bypass token your WAF looks for.
There is no headers field in the create wizard. Create the monitor with just its URL, then open it, click Edit, and find the Request Headers section. It's a single Headers (JSON) box holding a flat JSON object of name/value pairs:
{ "X-Api-Version": "2", "X-Tenant-Id": "acme" }The rules:
- It must be valid JSON, and a flat object of string values. Quote every value, including numbers —
{ "X-Api-Version": "2" }, not{ "X-Api-Version": 2 }. - Credentials do not go here.
AuthorizationandCookieare rejected; use the Authentication setting right below the box instead, which encrypts the secret at rest.Proxy-Authorizationis rejected for the same reason. - Headers that frame the HTTP message itself are rejected too, because Enori sets them for you:
Host,Content-Length,Transfer-Encoding,Connection,Proxy-Connection,Keep-Alive,Upgrade,TE,Trailer. Header names are matched case-insensitively, sohostis rejected exactly likeHost. - Names and values may not contain control characters or line breaks — that's a header-injection guard, and it rejects the save rather than silently stripping.
- Your headers are sent on every check, and they follow redirects only while the redirect stays on the same origin as the URL you configured. If a redirect crosses to another host, they're dropped for that hop — a token meant for your API is never handed to whatever a third-party redirect points at.
To clear them, empty the box and save.
Screenshot: the Edit modal's Request Headers section with a JSON object typed in.
Accepting more than one status code
The web form takes exactly one Expected Status. If your endpoint can legitimately answer with several codes — say 200 normally and 204 when there's no content — you can configure a set instead, through the REST API. There's no field for it in the create wizard or the edit modal yet, and the MCP server doesn't expose it either.
Send expectedStatusCodes as a list of strings on create or update:
{ "expectedStatusCodes": ["200", "204", "404"] }Each entry is one of two forms:
| Form | Example | Matches |
|---|---|---|
| Exact code | "204" | Exactly that code. Any code from 100 to 599. |
| Class wildcard | "2xx" | The whole class — 2xx matches 200–299. 1xx through 5xx, either case. |
A response is accepted if it matches any entry, so you can mix the two: ["2xx", "404"] means "any success, and also 404" — the combination a plain list of codes can't express. There is no range form (200-299); the wildcard covers that case.
The details worth knowing:
- The set wins. When it's non-empty, Expected Status is ignored entirely — so don't be surprised when the number in the web form no longer decides anything. The failure message names what's actually being asserted: "Expected status 200, 204 or 404, got 503".
- Limits: at most 20 entries. Duplicates are removed and entries are normalised (
" 2XX "is stored as2xx). - A bad entry is rejected outright with a 400 naming it — "ExpectedStatusCodes entry 'abc' is not a status code (100-599) or a class wildcard (1xx-5xx)". Nothing partial gets stored.
- Sending an empty list clears the set, putting the monitor back on its single Expected Status. Omitting the field entirely leaves the set untouched — so a PATCH that just renames the monitor won't wipe it.
- Changing the set triggers an immediate re-check, so you see the corrected verdict straight away instead of waiting out the interval.
Reading the results
Open a monitor to get its detail page.
The hero row
Six cells across the top: Status (with how long it's been in that state), Uptime, Response, Incidents (30d), Region, and Check schedule. The Uptime cell cycles between 7 / 30 / 90 days when you click it; the Response cell toggles between median (P50) and average. Both remember your choice.
The health banner
If something is wrong, a single banner sits under the hero showing the most severe current issue — down, certificate expired, check overdue, reputation flagged, security-header regression, broken certificate chain, content changed, deprecated TLS, or certificate expiring soon. Nothing renders when the monitor is healthy.
Uptime and response history
- The 90-day strip — one cell per day, coloured by that day's outcome, with incident pins beneath affected days. Hovering a day shows checks, failures, P50, P95, mean and incidents for it.
- The response-time chart — with anomaly dots on buckets more than 2σ above the range mean; hover one for the detail.
- The percentiles card — P50 / P95 / P99 for the selected range, with a change indicator against the previous period and a distribution histogram. When there aren't enough samples yet it tells you so rather than showing a misleading number.
All of these numbers are computed server-side over your actual check results.
Recent checks
Each row shows the status, response time, status code, and — where relevant — the redirect count and the final URL the request landed on. Expanding a failed check shows the response-header detail and a body snippet, plus the specific assertion that failed.
The right rail
Ten cards you can drag into whatever order suits you; the order is remembered per monitor:
SLO · Alerts · SSL · Last check breakdown (DNS / TCP / TLS / TTFB / download / total) · Security headers · Recent incidents · Domain · Maintenance · Status pages · Configuration.
Screenshot: a website monitor detail page — hero row, uptime strip, and the right rail.
Certificates
Any monitor on an https:// URL watches its TLS certificate automatically. Certificate details are refreshed at most every 6 hours — not on every check, because certificates change rarely and the handshake data would be identical thousands of times a day.
What the SSL card shows: expiry date and days remaining, issuer and subject, subject alternative names, key type and size, signature algorithm, the certificate chain with each link, TLS version and cipher suite, and a computed grade.
Certificate problems do not, by themselves, make your monitor Down. Enori is a monitoring service, not a browser — it completes the handshake and reports what it saw, so an expired or self-signed certificate doesn't produce a false "your site is down" page. Instead you get a dedicated alert:
| Alert | Fires when |
|---|---|
| SSL Expiring | Expiry falls inside your warning threshold (7 / 14 / 30 / 60 days). |
| SSL Expired | The certificate is past its expiry date. |
| SSL Renewed | A new certificate with a later expiry was seen — the all-clear. |
| SSL Chain Broken | The chain failed validation — a missing intermediate, an untrusted or self-signed root. |
| SSL Chain Restored | The chain validates again. |
| SSL Hostname Mismatch | The certificate is valid, but it isn't for the hostname you're monitoring. |
| SSL Hostname Restored | The certificate matches the monitored hostname again. |
| Weak TLS | The connection negotiated an outdated TLS version. |
| Weak Cipher | The negotiated cipher suite is weak. |
| TLS Upgraded / Cipher Restored | Back to acceptable. |
Each of these is a paired breach-and-recovery: you get one alert when the condition starts and one when it clears, not a reminder every check.
About hostname mismatch specifically. This is the "your browser would refuse to connect" case — the certificate is well-formed and its chain is trusted, but the name on it doesn't cover the host you asked for. It usually means a load balancer or CDN is serving the wrong certificate for that hostname, a wildcard doesn't stretch as far as you thought (*.example.com does not cover a.b.example.com), or a new subdomain was pointed at an origin whose certificate was never reissued.
What to expect from it:
- It's treated as serious — the same severity as a broken chain, because both make a real browser refuse the connection outright.
- A broken chain reports itself as Chain Broken, not as a mismatch. The hostname check only speaks up when the chain is otherwise clean, so one root cause gives you one alert to resolve rather than two.
- It's found by the daily certificate sweep, so it can take up to a day to reach you after the certificate changes — see the cadence note below.
The common practical cases:
- Self-signed certificate — connects fine, chain validation fails → SSL Chain Broken, and the grade drops.
- Missing intermediate — browsers on some platforms fail while others succeed; Enori sees it as a chain failure every time.
- Wrong certificate for the host — chain is fine, name doesn't match → SSL Hostname Mismatch.
- Expired — SSL Expired, plus a health banner. Your renewal cron probably stopped; check it.
- Auto-renewal working — you'll see SSL Renewed on the roughly-6-hourly cadence after the new certificate goes live, not instantly.
Two cadences, and which alerts come from which
| Cadence | What it produces |
|---|---|
| At most every 6 hours, off your monitor's own checks | Expiry date and chain validity — so SSL Expiring, SSL Expired, SSL Renewed, SSL Chain Broken, SSL Chain Restored. |
| A daily sweep, around 01:00 UTC | The rest of the certificate picture — TLS version, cipher suite and hostname match. So Weak TLS, Weak Cipher, their recoveries, and SSL Hostname Mismatch / SSL Hostname Restored. |
That's why a hostname or TLS problem can be up to ~24 hours behind the change that caused it, while an expiry or chain problem surfaces within hours. Neither cadence affects whether your monitor is Up — see above.
Alerts
Alerts from a website monitor go to the channels you selected — email, Slack, Discord, Microsoft Teams, webhooks, PagerDuty, SMS and mobile push. Channels are set up once in settings and then attached to monitors; see Alerts for the full picture, including escalation policies and on-call rotas.
What this monitor type can alert on:
| Alert | Trigger |
|---|---|
| Down | Failure threshold reached (and confirmed by other regions). |
| Recovered | Back to Up. |
| Degraded | A content assertion failed while the site was reachable — including a Does not contain keyword that showed up. |
| Slow response | Rolling-window P95 above your threshold. |
| Content changed | The page (or your selector) changed. |
| SSL | The certificate alerts listed above — expiry, chain, hostname mismatch, TLS and cipher. |
| Security header | Grade regression (baseline mode) or below-threshold (absolute mode). |
| Reputation | The URL got flagged, or cleared. |
Two things that stop alerts without you turning anything off:
- Maintenance windows — checks keep running, alerts and incidents are suppressed, and the window is excluded from your uptime figures.
- Snoozing — silence one monitor for a set period from its detail page. A contiguous run of suppressed checks in your history is almost always a snooze.
You can also set an SLO on a website monitor to track availability or latency against a target and alert on error-budget burn rather than on individual failures.
FAQ
Why is my monitor Down when the site loads fine in my browser?
In rough order of likelihood:
- Expected Status. It defaults to
200and matches exactly. An endpoint that returns201,204,301or302(with redirects off) is reported Down until you change the field. - A WAF or bot-protection rule is challenging the check. Your browser passes; an automated request doesn't. Allowlist the check IPs — see Monitoring IP Addresses — or set a custom User-Agent under Edit → Advanced.
- Geographic blocking. Your primary region may be blocked when your own location isn't. Try a different primary region.
- The timeout is too tight for a genuinely slow page. Default is 30 seconds; you can go to 120.
What's the difference between Down and Degraded again?
Down means the request failed or the response was structurally wrong — nobody answered, it timed out, the status code was wrong. Degraded means the site answered normally but your keyword, JSON or header assertion didn't match. Both are failures; the distinction tells you whether to look at infrastructure or at the application.
I enabled security header monitoring and immediately got an F. Did I break something?
No. Most sites grade F before anyone deliberately configures security headers — the web servers don't ship them. That's exactly why Baseline is the default mode: it records the F silently and only tells you if things get worse. If you want to actively improve the grade, work through the six headers in the table above, highest-weight first.
I got a content-change alert but I didn't change anything.
Something on the page changed that isn't your content — a rotating banner, a randomised A/B variant, an ad slot, a "last updated" line, a build hash in a script tag. Obvious dynamic values (timestamps, session IDs, CSRF tokens) are stripped automatically, but anything else on the page counts. The fix is a CSS selector narrowing the monitor to the region you actually care about.
Why is my certificate expiry still showing the old date after I renewed?
Certificate data refreshes at most every 6 hours, not every check. Wait for the next refresh.
How do I alert when text appears on a page, rather than disappears?
Set your Keyword to the text you don't want to see — Database error, Exception, Under maintenance — and set Keyword match to Does not contain. The check then fails when that text turns up. This is the right tool for an application that breaks while still returning a healthy 200.
Why can't I find the custom request headers field when creating a monitor?
Because it isn't there. Custom headers are an edit-time setting: create the monitor with its URL first, then open it, click Edit, and use the Request Headers section. The wizard deliberately stays short; anything the first check doesn't need lives in Edit.
Do my custom request headers get sent to redirect targets?
Only while the redirect stays on the same origin as the URL you configured. If a redirect takes the request to a different host, your custom headers are dropped for that hop — a header meant for your API shouldn't be handed to whatever a third-party redirect points at.
My endpoint returns 200 or 204 depending on the data. Can I accept both?
Yes, but not from the web form — it holds one code. Configure the set through the REST API with expectedStatusCodes, e.g. "200", "204"], or use a class wildcard like ["2xx"]. See [Accepting more than one status code.
I got an SSL Hostname Mismatch, but the site opens fine for me.
Check the exact hostname. A mismatch means the certificate being served doesn't cover the host in your monitor's URL, which most often bites on a subdomain a wildcard doesn't reach (*.example.com covers www.example.com but not api.eu.example.com), or on a host newly pointed at an origin whose certificate was never reissued. Your browser may be opening a different hostname than the one you're monitoring — compare them character for character. Note this check runs on the daily certificate sweep, so both the alert and its recovery lag the change by up to a day.
Can I monitor an internal or private URL?
No. Hostnames that resolve to private, internal or reserved addresses are rejected — on the original URL and on every redirect hop. Checks run from the public internet, so the target has to be publicly reachable.
Does a paused monitor still use one of my monitor slots?
Yes. Paused monitors count toward your plan's monitor limit. Delete monitors you no longer need, or add monitor slots — see Billing.
How many monitors and how much history do I get?
| Plan | Monitors | Check-result retention |
|---|---|---|
| Base | 10 | 30 days |
| Pro | 50 | 60 days |
| Business | 200 | 90 days |
Minimum check interval is 60 seconds on every plan; 30 seconds is an add-on.
Can I have two monitors on the same URL?
No — a URL can only be monitored once per account, and creating a duplicate returns "A monitor for this URL already exists." If you want to check the same endpoint two different ways, use two distinct URLs (a query string is enough) or put the second set of assertions on the same monitor.
I just created a monitor and it says Unknown with no data.
That's the expected first state. The first check is scheduled at a random moment inside the first interval rather than immediately, so monitors created together don't all fire at the same second forever. Wait one interval, or press Check Now.
Why did my monitor start checking every 30 seconds when I set 5 minutes?
It's Down. While a monitor is failing, Enori polls it every 30 seconds so recovery is picked up quickly, then returns to your configured interval.
Can I set this up without the UI?
Yes. The REST API and the MCP server both create and update website monitors. One option is currently API-only and reachable from neither the web forms nor MCP: the multi-code expectedStatusCodes set described above.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Every check is Down — unexpected HTTP status, and the status code shown looks fine | Expected Status is 200 and your endpoint returns something else | Edit → set Expected Status to the code your endpoint actually returns. If it can return several, configure a status-code set via the API. |
| Down with timed out, but the page loads slowly-but-fine for you | Timeout too low, or the origin is genuinely slow from that region | Raise Timeout (up to 120 s), and check the Last-check-breakdown card to see which phase is slow. |
| Down with too many redirects | A redirect loop, or a chain longer than 10 hops | Check the final URL on the Recent Checks row. Fix the loop, or point the monitor at the final URL. |
| Down with blocked target | The hostname resolves to a private/internal address, or a redirect lands on one | Point the monitor at a publicly reachable URL. |
| Down with response size out of range | A truncated, blank, or unexpectedly large response — or bounds set too tightly | Compare against the size on healthy checks; widen or clear the bounds. |
| Degraded with expected keyword not found, but the text is visibly on the page | The text is rendered by JavaScript | A website monitor fetches HTML; it doesn't run your JS. Assert on something present in the server-rendered response, or use a Browser monitor. |
| Degraded with expected keyword not found, and the text is definitely in the HTML | Keyword match is set to Contains (case-sensitive) and the case differs | Switch to plain Contains, or match the case exactly. |
| Degraded, and the reason reads "Forbidden keyword … was found" | That's Does not contain mode working as designed — the text you're watching for appeared | Look at the page. If you meant the opposite assertion, switch Keyword match back to Contains. |
| Degraded on every check, reason "Invalid keyword regex …" | Regex mode with a pattern that doesn't compile — this isn't caught when you save | Fix the pattern in Edit, then press Check Now to confirm it compiles. |
| Degraded on every check, reason "Keyword regex … timed out after 1s" | The pattern backtracks badly against a large page | Simplify it — anchor it, avoid nested quantifiers like (a+)+, or match a plain substring with Contains instead. |
| Degraded with JSON validation failed, and the path looks right | Unsupported path syntax, or the response isn't JSON | Paths must start with $.; recursive descent (..) and filters ([?()]) aren't supported. Check the actual value shown on the failed check. |
| Constant flapping between Up and Down | A genuinely marginal endpoint, or too sensitive a threshold | Raise When to alert to 3 or 5 consecutive failures; if it's a slow endpoint, raise the timeout. |
| Alerts stopped arriving but checks look fine | Monitor is snoozed, or inside a maintenance window | Check the Maintenance card and the snooze state on the detail page. |
| Nothing at all is being checked | Monitor is paused | Resume it from the monitor's action bar. Paused monitors still count toward your plan limit. |
Related documentation
- Alerts — channels, alert rules, escalation policies, on-call rotas.
- Notifications — the in-app bell, and how it differs from alert channels.
- Maintenance Windows — suppress alerts for planned work and exclude it from uptime.
- Service Level Objectives — reliability targets and error-budget alerting.
- Uptime Reports — on-demand uptime and SLA reports.
- Timeline — every event across all your monitors on one calendar.
- Monitoring IP Addresses — allowlisting Enori's checks.
- Billing & Subscription — plans, limits and add-ons.
Feedback or corrections: support@enori.io