# Website Uptime Monitor (`khadinakbar/website-uptime-monitor`) Actor

Bulk uptime monitor returning HTTP status, SSL expiry, content match, response time, A-F performance grade, 0-100 health score, and a specific failure diagnostic per URL — all in one call. Built for DevOps, SREs, SaaS founders, agencies, and AI agents.

- **URL**: https://apify.com/khadinakbar/website-uptime-monitor.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** Developer tools, Automation, SEO tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 url checkeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Website Uptime Monitor — Health Score, SSL, Content Match

Bulk uptime monitor for websites and APIs. One call returns HTTP status, SSL certificate expiry, content keyword match, response time, an A–F performance grade, a composite **0–100 health score**, and a specific **failure diagnostic** (DNS, SSL, timeout, 5xx, content mismatch, …) per URL.

Built for **DevOps teams, SRE engineers, SaaS founders, agencies, and AI agents** that need to verify a site is actually working — not just returning a status code.

### What you get per URL

| Field | Meaning |
|---|---|
| `isUp` | `true` only if the URL returned an expected status AND any keyword match passed |
| `healthScore` | 0–100, penalized for slow responses, SSL issues, redirects, content mismatches |
| `performanceGrade` | A (<300 ms), B (<600 ms), C (<1.2 s), D (<2.5 s), F (slower or down) |
| `statusCode` / `statusText` | Final HTTP status after redirects |
| `responseTimeMs` | Time to final response in milliseconds |
| `ssl` | Issuer, valid-from, valid-to, days until expiry, expired/expiring flags |
| `contentMatch` | Whether the response body contains your keyword or matches your regex |
| `redirects` | Ordered chain of every hop |
| `headers` | Server, content-type, content-length, cache-control, x-powered-by |
| `diagnostic` | When down: `kind` (`dns_error`, `ssl_expired`, `timeout`, `5xx`, …) + `message` + actionable `suggestion` |

A **run summary** and a **shareable HTML report** are also written to the default key-value store.

### Why this monitor

Most uptime checkers tell you "the server replied with 200." That's not enough. A 200 with the wrong content (broken React app, blank page, "Maintenance" splash) is still **down** for your users. Your monitor should know.

This actor combines:

1. **HTTP status + redirects** — what every checker does.
2. **SSL inspection** — issuer, expiry date, "expiring in N days" warnings (avoid the typical "we forgot to renew" outage).
3. **Content match** — verify the page actually contains the text it should ("Sign up", "Add to cart", "OK").
4. **Performance grade** — instant signal for slow-down detection.
5. **Composite health score** — one 0–100 number an agent or dashboard can branch on.
6. **Failure diagnostics** — when down, the actor tells you *why* and *what to do*.

### Quick start

#### Apify Console

1. Open the actor and click **Start**.
2. Add URLs to **URLs to monitor**.
3. (Optional) set a **Content keyword** like `Sign up` to verify the page rendered.
4. Click **Start** and watch results stream in.

#### Apify API (curl)

```bash
curl -X POST "https://api.apify.com/v2/acts/khadinakbar~website-uptime-monitor/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "startUrls": [
      { "url": "https://example.com" },
      { "url": "https://api.example.com/health" }
    ],
    "keyword": "OK",
    "checkSsl": true,
    "timeoutMs": 15000
  }'
````

#### JavaScript (apify-client)

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('khadinakbar/website-uptime-monitor').call({
    startUrls: [{ url: 'https://example.com' }],
    keyword: 'Example Domain',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0].healthScore, items[0].diagnostic);
```

#### Python (apify-client)

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_TOKEN")
run = client.actor("khadinakbar/website-uptime-monitor").call(run_input={
    "startUrls": [{"url": "https://example.com"}],
    "keyword": "Example Domain",
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["url"], item["healthScore"], item["diagnostic"])
```

#### MCP (Claude / GPT / agents)

Once available in the Apify MCP server, an agent can call:

```
apify--website-uptime-monitor
  startUrls: [{ url: "https://example.com" }]
  keyword: "Sign up"
```

and branch on the returned `healthScore`. Sub-second for a single URL, capped cost ≈ `$0.002` + `$0.00005` start.

### Pricing — Pay Per Event

| Event | Price | When charged |
|---|---|---|
| `actor-start` | **$0.00005** per GB-RAM | Once when the run starts (covers compute usage) |
| `url-checked` | **$0.002** per URL | Each URL that completes (up or down) |

**Examples:**

- 1 URL agent call → `$0.002 + $0.00005 ≈ $0.0021`
- 50 URL daily run → `$0.10 + $0.00005 ≈ $0.10`
- 1,000 URL bulk audit → `$2.00 + $0.00005 ≈ $2.00`
- 10,000 URL run → `$20.00 + $0.00005 ≈ $20.00`

No hidden setup fees. No per-result tier traps. Failed URLs are charged the same as successful ones because they consume the same work and produce the same diagnostic data.

### Input fields

| Field | Type | Default | Notes |
|---|---|---|---|
| `startUrls` | array of `{ url }` | sample 3 URLs | Standard Apify URL list |
| `urls` | array of strings | `[]` | Simpler alternative for AI agents |
| `keyword` | string | `null` | Case-insensitive substring required in body |
| `regex` | string | `null` | Case-insensitive regex required in body (overrides `keyword`) |
| `expectedStatusCodes` | array of integers | `[]` (= 2xx/3xx OK) | Strict allowlist e.g. `[200]` |
| `method` | enum | `GET` | `GET` / `HEAD` / `POST` / `PUT` / `DELETE` / `OPTIONS` |
| `checkSsl` | boolean | `true` | Inspect SSL on HTTPS URLs |
| `followRedirects` | boolean | `true` | Follow 3xx |
| `maxRedirects` | integer | `5` | Hop limit |
| `timeoutMs` | integer | `30000` | Per-request timeout |
| `maxConcurrency` | integer | `20` | Parallel workers (1–100) |
| `userAgent` | string | default UA | Custom UA |
| `useApifyProxy` | boolean | `false` | Route through Apify proxy |
| `proxyConfiguration` | object | `{}` | Full proxy config |

### Output

#### Dataset (one item per URL)

```json
{
  "url": "https://example.com/",
  "isUp": true,
  "healthScore": 100,
  "performanceGrade": "A",
  "statusCode": 200,
  "statusText": "OK",
  "responseTimeMs": 187,
  "ssl": {
    "checked": true,
    "valid": true,
    "issuer": "Let's Encrypt",
    "subject": "example.com",
    "daysUntilExpiry": 64,
    "isExpired": false,
    "isExpiringSoon": false
  },
  "contentMatch": {
    "checked": true,
    "found": true,
    "keyword": "Example Domain",
    "matchType": "keyword"
  },
  "redirects": [],
  "finalUrl": "https://example.com/",
  "headers": {
    "server": "ECAcc (lac/55B0)",
    "contentType": "text/html; charset=UTF-8",
    "contentLength": 1256
  },
  "diagnostic": null,
  "checkedAt": "2026-05-03T19:55:00.000Z",
  "durationMs": 213
}
```

#### Key-value store

| Key | Type | Description |
|---|---|---|
| `SUMMARY` | JSON | Aggregated metrics: total / up / down, uptime %, avg response time, avg health score, SSL/grade/diagnostic breakdowns |
| `REPORT` | HTML | Sortable table report, shareable link |
| `RUN_CONFIG` | JSON | Snapshot of effective run settings |

### Diagnostic kinds

When `isUp` is `false` (or quality is degraded), `diagnostic.kind` will be one of:

| Kind | Meaning |
|---|---|
| `dns_error` | DNS lookup failed (`ENOTFOUND`, `EAI_AGAIN`) |
| `connection_refused` | Server actively refused the connection |
| `connection_reset` | Server closed the connection mid-flight |
| `timeout` | Request exceeded `timeoutMs` |
| `ssl_error` | SSL handshake failed (untrusted, self-signed, …) |
| `ssl_expired` | Certificate expiration date in the past |
| `4xx` | Client error (404 / 403 / 429 / …) |
| `5xx` | Server error |
| `content_mismatch` | Response OK but `keyword` / `regex` not found |
| `network_error` | Other network failure |
| `invalid_url` | URL string could not be parsed |
| `internal_error` | Bug in the actor (please report) |

Each diagnostic includes a `message` and an actionable `suggestion`.

### Use cases

- **SaaS founders** — daily check that landing pages, signup, and pricing pages are alive and contain the right text.
- **DevOps / SRE** — pre-deploy and post-deploy uptime sweeps with content verification (your `/health` endpoint really returns `OK`).
- **Agencies** — white-label client uptime reports with SSL expiry warnings 30 days ahead.
- **E-commerce** — verify product pages render the **Add to cart** button before peak traffic events.
- **AI agents** — pre-flight check before scraping or transacting against a target ("is this site up?").
- **Marketing teams** — confirm campaign landing pages are live before launching ads.
- **SEO** — detect 404s, redirect chains, and slow pages affecting crawl budget and rankings.

### Health score formula

Starting from 100, the score is reduced by:

- **Status code:** −10 if 3xx, −50 if 4xx, −80 if 5xx
- **Response time:** −5 (>600 ms), −10 (>1.2 s), −20 (>2.5 s), −30 (>5 s)
- **SSL:** −10 if expiring within 30 days, −25 if invalid, −40 if expired
- **Content:** −30 if `keyword`/`regex` not found
- **Diagnostic:** capped at 30 if any diagnostic is present

A 100 means: 200 status, fast response, valid SSL with >30 days left, content match passed.

### Scheduling and alerting

Pair with Apify Scheduler to run every N minutes/hours. Combine with the Apify webhooks (built-in) to ping Slack / Discord / PagerDuty / your own endpoint when a run produces any `isUp: false` records.

For full alert workflows, route the dataset into n8n / Make / Zapier — every modern automation tool has an Apify connector.

### FAQ

**Why is `isUp: false` even though `statusCode: 200`?**
Because your `keyword` or `regex` did not match the response body. The page returned but didn't render the expected text — usually a soft failure that only this monitor will catch.

**Why is SSL `checked: false`?**
The URL is plain HTTP (not HTTPS), or you set `checkSsl: false`.

**Can I monitor APIs that require headers/auth?**
Currently, custom request headers and bodies aren't input fields. Open an issue if you need them — easy add.

**Does it support POST checks?**
Yes — set `method` to `POST` (or any HTTP verb). The body is empty for now.

**Can I run from a specific country?**
Yes — set `useApifyProxy: true` and configure `proxyConfiguration.countryCode` (e.g., `"DE"`).

**What's the maximum concurrency?**
100\. Default is 20, which handles bulk runs of 1,000+ URLs in seconds.

### Legal & disclaimer

This actor only sends standard HTTP requests with a transparent User-Agent (`ApifyUptimeMonitor/1.0`). It does not bypass security, scrape protected content, or store any credentials. You are responsible for ensuring you have permission to monitor any URL you submit; do not use this actor against sites where you have no authorization. By using this actor you agree to the Apify Store [Terms of Use](https://apify.com/store/terms-of-use).

### Related actors by khadinakbar

- [Broken Link Checker](https://apify.com/khadinakbar/broken-link-checker) — find every broken link on a site.
- [Bulk Website Contact Extractor](https://apify.com/khadinakbar/bulk-website-contact-extractor) — pull emails/phones/socials from any list of domains.
- [Contact Details Scraper](https://apify.com/khadinakbar/contact-details-scraper) — single-domain contact extraction.

See the full portfolio at <https://apify.com/khadinakbar>.

# Actor input Schema

## `startUrls` (type: `array`):

List of website URLs to check (each as { url: 'https://example.com' }). Supports any HTTPS or HTTP URL — landing pages, APIs, status endpoints. Default: three sample URLs. Use this OR the simpler 'urls' array — both are accepted.

## `urls` (type: `array`):

Alternative simple input: a flat array of URL strings (e.g., \['https://a.com','https://b.com']). Combined with 'startUrls' if both provided. Useful for AI agents passing a plain list. Either field is fine.

## `keyword` (type: `string`):

If set, the response body must contain this case-insensitive substring or the URL is marked DOWN with diagnostic 'content\_mismatch' (e.g., 'Sign up' to verify a landing page rendered). Leave empty to skip content verification. NOT a regex — for regex use the 'regex' field below.

## `regex` (type: `string`):

If set, the response body must match this case-insensitive JavaScript regular expression or the URL is marked DOWN (e.g., 'sign\s\*up|register'). Takes precedence over 'keyword' when both are set. Leave empty to skip.

## `expectedStatusCodes` (type: `array`):

List of HTTP status codes considered 'up' (e.g., \[200, 301, 302]). Default accepts 2xx and 3xx as up. Use to enforce strict checks like '\[200]' only. Codes outside the list mark the URL as DOWN.

## `method` (type: `string`):

HTTP method used for each check. GET is the safe default and works for almost all sites. HEAD is faster and lighter but some servers respond differently. POST/PUT/DELETE only for API endpoints you own.

## `checkSsl` (type: `boolean`):

When true (default), the actor inspects the SSL certificate of every HTTPS URL and reports issuer, expiry, and warns if expiring in ≤30 days. Set false to skip the TLS inspection (faster, but you lose SSL diagnostics). Has no effect on plain HTTP URLs.

## `followRedirects` (type: `boolean`):

When true (default), 301/302/307/308 redirects are followed up to maxRedirects and the final URL is returned in 'finalUrl'. Set false to inspect the raw redirect response. Most uptime checks should leave this on.

## `maxRedirects` (type: `integer`):

Maximum number of redirect hops to follow before giving up. Default 5. Increase for sites with long redirect chains. Lower to detect redirect loops earlier.

## `timeoutMs` (type: `integer`):

Per-request timeout in milliseconds. Default 30,000 (30 s). Raise for slow APIs / cold-start endpoints. Lower to fail fast on unreachable hosts. Applies to both HTTP and SSL inspection.

## `maxConcurrency` (type: `integer`):

How many URLs to check in parallel. Default 20. Higher = faster bulk runs but more memory and proxy load. Drop to 5 for tiny actors / shared environments. Bounded 1-100.

## `userAgent` (type: `string`):

Override the default User-Agent header (e.g., 'MyMonitor/1.0'). Some sites cloak responses based on UA. Leave empty for the default 'Mozilla/5.0 ApifyUptimeMonitor/1.0' string.

## `useApifyProxy` (type: `boolean`):

When true, all checks go through Apify's proxy network, useful for geo-restricted sites or rate-limited endpoints. Default false (direct connection from Apify infrastructure). Costs extra proxy GB. Configure region in 'proxyConfiguration'.

## `proxyConfiguration` (type: `object`):

Full Apify proxy configuration object — set group, country, etc. Overrides 'useApifyProxy' if provided. Leave default {} for direct connections. See https://docs.apify.com/proxy.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.google.com"
    },
    {
      "url": "https://www.github.com"
    },
    {
      "url": "https://example.com"
    }
  ],
  "urls": [],
  "keyword": "Sign up",
  "regex": "sign\\s*up|register",
  "expectedStatusCodes": [
    200,
    201,
    204
  ],
  "method": "GET",
  "checkSsl": true,
  "followRedirects": true,
  "maxRedirects": 5,
  "timeoutMs": 30000,
  "maxConcurrency": 20,
  "useApifyProxy": false,
  "proxyConfiguration": {}
}
```

# Actor output Schema

## `urlResults` (type: `string`):

No description

## `downloadCsv` (type: `string`):

No description

## `summaryJson` (type: `string`):

No description

## `htmlReport` (type: `string`):

No description

## `runConfig` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "startUrls": [
        {
            "url": "https://www.google.com"
        },
        {
            "url": "https://www.github.com"
        },
        {
            "url": "https://example.com"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/website-uptime-monitor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "startUrls": [
        { "url": "https://www.google.com" },
        { "url": "https://www.github.com" },
        { "url": "https://example.com" },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("khadinakbar/website-uptime-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "startUrls": [
    {
      "url": "https://www.google.com"
    },
    {
      "url": "https://www.github.com"
    },
    {
      "url": "https://example.com"
    }
  ]
}' |
apify call khadinakbar/website-uptime-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=khadinakbar/website-uptime-monitor",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Website Uptime Monitor",
        "description": "Bulk uptime monitor returning HTTP status, SSL expiry, content match, response time, A-F performance grade, 0-100 health score, and a specific failure diagnostic per URL — all in one call. Built for DevOps, SREs, SaaS founders, agencies, and AI agents.",
        "version": "0.2",
        "x-build-id": "NpKTtdfw4Np4lGFWy"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/khadinakbar~website-uptime-monitor/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-khadinakbar-website-uptime-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/khadinakbar~website-uptime-monitor/runs": {
            "post": {
                "operationId": "runs-sync-khadinakbar-website-uptime-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/khadinakbar~website-uptime-monitor/run-sync": {
            "post": {
                "operationId": "run-sync-khadinakbar-website-uptime-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "startUrls": {
                        "title": "URLs to monitor",
                        "type": "array",
                        "description": "List of website URLs to check (each as { url: 'https://example.com' }). Supports any HTTPS or HTTP URL — landing pages, APIs, status endpoints. Default: three sample URLs. Use this OR the simpler 'urls' array — both are accepted.",
                        "items": {
                            "type": "object",
                            "required": [
                                "url"
                            ],
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "title": "URL of a web page",
                                    "format": "uri"
                                }
                            }
                        }
                    },
                    "urls": {
                        "title": "URLs (simple array, optional)",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Alternative simple input: a flat array of URL strings (e.g., ['https://a.com','https://b.com']). Combined with 'startUrls' if both provided. Useful for AI agents passing a plain list. Either field is fine.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "keyword": {
                        "title": "Content keyword (optional)",
                        "type": "string",
                        "description": "If set, the response body must contain this case-insensitive substring or the URL is marked DOWN with diagnostic 'content_mismatch' (e.g., 'Sign up' to verify a landing page rendered). Leave empty to skip content verification. NOT a regex — for regex use the 'regex' field below."
                    },
                    "regex": {
                        "title": "Content regex (optional)",
                        "type": "string",
                        "description": "If set, the response body must match this case-insensitive JavaScript regular expression or the URL is marked DOWN (e.g., 'sign\\s*up|register'). Takes precedence over 'keyword' when both are set. Leave empty to skip."
                    },
                    "expectedStatusCodes": {
                        "title": "Expected status codes (optional)",
                        "type": "array",
                        "description": "List of HTTP status codes considered 'up' (e.g., [200, 301, 302]). Default accepts 2xx and 3xx as up. Use to enforce strict checks like '[200]' only. Codes outside the list mark the URL as DOWN.",
                        "default": []
                    },
                    "method": {
                        "title": "HTTP method",
                        "enum": [
                            "GET",
                            "HEAD",
                            "POST",
                            "PUT",
                            "DELETE",
                            "OPTIONS"
                        ],
                        "type": "string",
                        "description": "HTTP method used for each check. GET is the safe default and works for almost all sites. HEAD is faster and lighter but some servers respond differently. POST/PUT/DELETE only for API endpoints you own.",
                        "default": "GET"
                    },
                    "checkSsl": {
                        "title": "Inspect SSL certificate",
                        "type": "boolean",
                        "description": "When true (default), the actor inspects the SSL certificate of every HTTPS URL and reports issuer, expiry, and warns if expiring in ≤30 days. Set false to skip the TLS inspection (faster, but you lose SSL diagnostics). Has no effect on plain HTTP URLs.",
                        "default": true
                    },
                    "followRedirects": {
                        "title": "Follow redirects",
                        "type": "boolean",
                        "description": "When true (default), 301/302/307/308 redirects are followed up to maxRedirects and the final URL is returned in 'finalUrl'. Set false to inspect the raw redirect response. Most uptime checks should leave this on.",
                        "default": true
                    },
                    "maxRedirects": {
                        "title": "Max redirects",
                        "minimum": 0,
                        "maximum": 20,
                        "type": "integer",
                        "description": "Maximum number of redirect hops to follow before giving up. Default 5. Increase for sites with long redirect chains. Lower to detect redirect loops earlier.",
                        "default": 5
                    },
                    "timeoutMs": {
                        "title": "Request timeout (ms)",
                        "minimum": 1000,
                        "maximum": 300000,
                        "type": "integer",
                        "description": "Per-request timeout in milliseconds. Default 30,000 (30 s). Raise for slow APIs / cold-start endpoints. Lower to fail fast on unreachable hosts. Applies to both HTTP and SSL inspection.",
                        "default": 30000
                    },
                    "maxConcurrency": {
                        "title": "Max concurrency",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "How many URLs to check in parallel. Default 20. Higher = faster bulk runs but more memory and proxy load. Drop to 5 for tiny actors / shared environments. Bounded 1-100.",
                        "default": 20
                    },
                    "userAgent": {
                        "title": "Custom User-Agent (optional)",
                        "type": "string",
                        "description": "Override the default User-Agent header (e.g., 'MyMonitor/1.0'). Some sites cloak responses based on UA. Leave empty for the default 'Mozilla/5.0 ApifyUptimeMonitor/1.0' string."
                    },
                    "useApifyProxy": {
                        "title": "Route through Apify proxy",
                        "type": "boolean",
                        "description": "When true, all checks go through Apify's proxy network, useful for geo-restricted sites or rate-limited endpoints. Default false (direct connection from Apify infrastructure). Costs extra proxy GB. Configure region in 'proxyConfiguration'.",
                        "default": false
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration (advanced)",
                        "type": "object",
                        "description": "Full Apify proxy configuration object — set group, country, etc. Overrides 'useApifyProxy' if provided. Leave default {} for direct connections. See https://docs.apify.com/proxy.",
                        "default": {}
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
