A MongoDB-style query language for defining exactly when a monitor is up or down.
A PingQL query is a JSON object that runs against every ping result. If the query evaluates to true, the monitor is considered up. Use $consider: "down" to invert this.
By default (no query set), a monitor is up when the HTTP status code is below 400.
These are the values you can query against:
| Field | Type | Description |
|---|---|---|
| status | number | HTTP status code (e.g. 200, 404) |
| body | string | Full response body as text |
| headers.name | string | Response header value (e.g. headers.content-type) |
| $responseTime | number | Request latency in milliseconds |
| $certExpiry | number | Days until SSL certificate expires |
| $json | object | JSONPath expression against response body — see below |
| $select | object | CSS selector against response HTML — see below |
| Operator | Description | Types |
|---|---|---|
| $eq | Equal to | any |
| $ne | Not equal to | any |
| $gt | Greater than | number |
| $gte | Greater than or equal | number |
| $lt | Less than | number |
| $lte | Less than or equal | number |
| $contains | String contains substring | string |
| $startsWith | String starts with | string |
| $endsWith | String ends with | string |
| $regex | Matches regular expression | string |
| $exists | Field is present and non-null | any |
| $in | Value is in array | any |
// Up if status is 200 { "status": 200 } // Up if status is 2xx or 3xx { "status": { "$lt": 400 } }
// Up if body contains "healthy" { "body": { "$contains": "healthy" } } // Up if body matches a regex { "body": { "$regex": "status.*(ok|healthy)" } }
// Up if response is JSON { "headers.content-type": { "$contains": "application/json" } }
// Up if response is under 500ms { "$responseTime": { "$lt": 500 } }
// Up if cert expires in more than 14 days { "$certExpiry": { "$gt": 14 } }
Use $json to extract and compare a value from a JSON response body. The key is a dot-notation path, the value is a condition.
// Up if response JSON has { "status": "ok" } { "$json": { "$.status": { "$eq": "ok" } } } // Up if search index has >= 1000 entries { "$json": { "$.data.count": { "$gte": 1000 } } } // Nested path { "$json": { "$.db.connections.active": { "$lt": 100 } } }
Use $select to extract text from an HTML response using a CSS selector. Useful for monitoring public-facing pages where there's no API.
// Up if h1 text is "Example Domain" { "$select": { "h1": { "$eq": "Example Domain" } } } // Up if status badge contains "operational" { "$select": { ".status-badge": { "$contains": "operational" } } }
// Up if status is 200 AND body contains "ok" { "$and": [ { "status": 200 }, { "body": { "$contains": "ok" } } ] } // Up if status is 200 OR 204 { "$or": [ { "status": 200 }, { "status": 204 } ] } // Up if status is NOT 500 { "$not": { "status": 500 } }
By default, a query returning true means the monitor is up. Set $consider: "down" to invert this — if the conditions match, the monitor is down.
// DOWN if response time exceeds 2 seconds { "$consider": "down", "$responseTime": { "$gt": 2000 } } // DOWN if cert expires in less than 7 days { "$consider": "down", "$certExpiry": { "$lt": 7 } } // DOWN if any of these match { "$consider": "down", "$or": [ { "status": { "$gte": 500 } }, { "$responseTime": { "$gt": 5000 } } ] }
You can add multiple monitors pointing to the same URL with different queries — one for uptime, one for performance, one for content integrity.
// Monitor 1: basic uptime { "status": { "$lt": 400 } } // Monitor 2: performance — down if slow { "$consider": "down", "$responseTime": { "$gt": 1000 } } // Monitor 3: content — check API response shape { "$and": [ { "status": 200 }, { "$json": { "$.ok": { "$eq": "true" } } } ] }