---
title: HTTP(S) monitors
description: Check a URL's status code, response time and body — with custom methods, headers, redirects, TLS verification and assertions.
sidebar:
  label: HTTP(S)
---

{/* Source of truth: packages/shared/src/monitors.ts — httpConfigSchema. */}

An HTTP monitor makes a request to a URL and decides whether the response was
good. It is the type most people start with.

## Minimum setup

A URL and an interval. By default Glowo sends a `GET`, follows up to 5
redirects, verifies TLS, and treats any 2xx as healthy.

## Request options

| Option | Allowed values | Default |
| --- | --- | --- |
| `method` | `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD`, `OPTIONS` | `GET` |
| `headers` | up to 20; names must be valid tokens, values max 4096 chars | none |
| `body` | up to 65536 characters (64 KiB) | none |
| `basicAuth` | `username` + `password`, 255 characters each | none |
| `followRedirects` | boolean | `true` |
| `maxRedirects` | 0–10 | 5 |
| `verifySsl` | boolean | `true` |
| `targetIp` | a valid IPv4 or IPv6 address | none |

Header values may not contain carriage returns or line feeds — that is a
response-splitting vector and is rejected at validation.

### Pinning the target IP

`targetIp` sends the request to a specific address while keeping the URL's
hostname in the `Host` header and TLS SNI. That lets you check one node behind a
DNS round-robin, or verify a new server before you move DNS to it.

## Deciding pass or fail

### Expected status codes

`expectedStatusCodes` accepts up to 10 codes. Set it when a healthy response is
not a 2xx — an endpoint that correctly returns `401` to an unauthenticated
probe, for example.

### Response-time thresholds

| Option | Effect |
| --- | --- |
| `degradedAfterMs` | Slower than this → `DEGRADED` |
| `failedAfterMs` | Slower than this → `DOWN` |

Both are independent of `timeout`. `timeout` is when Glowo gives up on the
request entirely; these thresholds judge a response that *did* arrive.

### Assertions

For anything about the body, headers or timing, use
[assertions](/monitors/assertions) — up to 20 per monitor, each able to mark the
result `DEGRADED` or `DOWN`.

:::note
`bodyAssertion` is a legacy single-rule field kept for older monitors. New
monitors should use `assertions`, which covers everything it did and more.
:::

## A worked example

Checking a JSON health endpoint that must return 200, respond within 800 ms, and
report `"status": "ok"`:

- **Method** `GET`, **URL** `https://api.example.com/health`
- **Expected status codes** `200`
- **degradedAfterMs** `800`
- **Assertion** — source `json_body`, property `status`, comparison `equals`,
  value `ok`, severity `fail`

Anything slower than 800 ms shows as degraded on your status page without
paging anyone; a wrong `status` value pages you.
