- The server answered. Your visitor still has a problem.
- A green light needs a clear meaning
- Can it be reached?
- Is this the right page?
- Can a visitor use it?
- What “200 OK” actually tells you
- Check one page that matters
- Make one request and inspect what came back
- Make a harmless failure on purpose
- One passing request is a useful beginning
- Before you continue
- Let the result reach your phone.
- References and further reading
The server answered. Your visitor still has a problem.
Imagine opening your website and finding a maintenance message instead of your latest article. Your monitor is green. It received a response, so it called the site “up.”
Both observations can be true. A website can answer a request without delivering the page someone came to use. A useful check needs to look beyond the fact that something replied.
A green light needs a clear meaning
For a public article, “working” might mean that the correct URL returns the article within an acceptable time. For a shop, it might mean that someone can view a product and complete a checkout. Those are different promises.
Start with the visitor’s goal. Then choose a check that provides evidence for that goal. Do not let a convenient test silently become your definition of a healthy website.
Can it be reached?
The monitoring machine can resolve the name and complete the network request.
Is this the right page?
The response has the expected HTTP status and a meaningful piece of the expected content.
Can a visitor use it?
The browser loads what matters, and the important interaction actually works.
Our first check will cover part of the first two questions. A browser test is needed for behavior that depends on JavaScript or a sequence of actions.
What “200 OK” actually tells you
An HTTP status is a short code sent with a web response.
For a normal page request, 200 OK means the request
succeeded at the HTTP level. It does not certify every feature
on that page.
An application can mistakenly return 200 with an
error message. A cached page can load while a database-backed
feature is broken. A login form can appear while submitting it fails.
Check one page that matters
Pick a public page you own or have permission to test. Choose a stable sentence or marker that should appear in its returned HTML. An article title can work for a simple publishing site; a site-wide logo is usually too broad.
| Check | Useful evidence | Still unproven |
|---|---|---|
| Request completes | This machine received a response. | Other locations can reach the site. |
| Expected status | The final response has the code you expect. | Its content is the page you wanted. |
| Expected text | A chosen marker appears in the response body. | The whole page is correct or current. |
| Time limit | The request completed within your allowed time. | A visitor’s browser renders quickly. |
| Browser journey | A selected interaction works in the tested environment. | Every feature works for every visitor. |
What makes a weak content marker?
A footer, navigation label or brand name may appear on both a good page and an error page. Pick something specific to the response you need. A single marker is still a limited test: it can remain present on a partly broken page.
Make one request and inspect what came back
You need Bash, curl, grep and
mktemp on your Linux machine. This exercise does not
change your website or require sudo. It makes one
request, although following redirects may make additional requests.
The sample uses example.com and the marker
Example Domain for a one-off demonstration.
Its availability is not guaranteed. Before using your own page,
change both values to the real URL and text you
expect in its HTML. Do not schedule checks against the example domain.
(
site_url='https://example.com/'
expected_text='Example Domain'
response_file=$(mktemp) || exit 1
trap 'rm -f -- "$response_file"' EXIT
if http_code=$(curl --silent --show-error \
--location --max-redirs 3 \
--connect-timeout 5 --max-time 15 \
--output "$response_file" \
--write-out '%{http_code}' \
"$site_url"); then
:
else
printf 'CHECK FAILED: request did not complete.\n'
exit 1
fi
if [ "$http_code" != '200' ]; then
printf 'CHECK FAILED: expected HTTP 200; got %s.\n' "$http_code"
exit 1
fi
if ! grep --fixed-strings --quiet -- "$expected_text" "$response_file"; then
printf 'CHECK FAILED: expected text was not found or could not be read.\n'
exit 1
fi
printf 'CHECK PASSED: HTTP 200 and expected text received.\n'
)
The parentheses keep the variables and exit commands inside a subshell. A temporary file holds the response body and is removed when the block exits.
The request has a five-second connection limit and a fifteen-second
total limit. It follows up to three redirects. For this public-page
example, the final response must be 200.
Another endpoint may need a different rule.
Why check both curl’s result and the HTTP code?
Without a fail option, curl can complete a transfer successfully even when the server returns an HTTP error. The first check catches a failed transfer; the second checks the final HTTP response. The content check then looks for the chosen text.
What if the page uses JavaScript?
Curl downloads the response but does not run the page’s JavaScript. Text inserted later by browser code may be absent. Inspect the original HTML before choosing a marker, or use a browser-based check for the behavior you need.
Make a harmless failure on purpose
Run the block once with the expected values. If it passes, change
only expected_text to
SA_MONITOR_MARKER_NOT_PRESENT_7F3A
and run it again.
The second run should report a content failure, assuming that string is absent from the returned page. You changed the test expectation, not the website. Restore the correct marker afterward.
If the wrong marker still passes, stop. Check which block you ran and whether the marker is actually present. A monitor that never reports failure has not earned your trust.
| Result | What to inspect next |
|---|---|
| Request did not complete | Read curl’s error: name resolution, connection, TLS, redirect or timeout problems need different fixes. |
| Unexpected HTTP code | Check the URL, access requirements and application response. |
| Expected text missing or unreadable | Check the response, marker, redirects and local file access. The website is not automatically the cause. |
| Check passed | This request met the chosen status, content and time rules. Other pages and browser interactions remain untested. |
One passing request is a useful beginning
This is a one-time observation from one machine. It does not tell you what happened an hour ago, whether another region has a connection problem, or whether a visitor can sign in.
A check running on the web server can also take a different network path from visitors. If that server loses power, its local checker stops too. We will address the observation point in Lesson 03.
For now, write down your check’s promise in one sentence:
That is specific enough to test. “The whole website works” is not what this small script establishes.
For the supporting concepts, read how DNS finds your server and how Linux exit codes report success and failure.
Before you continue
- Why can an HTTP 200 response still disappoint a visitor?
- Why is a site-wide footer a weak marker?
- What does changing the expected marker test?
- Can this curl check verify a JavaScript checkout?
- What happens to a local checker when its server loses power?
Check your answers
- The status describes the HTTP request. The response may contain the wrong content, and an important feature may still fail.
- The same footer may appear on an error page, so it does not identify the intended content well.
- It tests whether a missing marker produces a failure result. It does not simulate every outage.
- No. Curl does not execute the page’s JavaScript or complete a browser journey.
- The checker stops with the server, so it cannot report that event by itself.








