# How to Create a Custom Monitor Type Plugin for Uptime Kuma

> Learn how to create a custom monitor type plugin for Uptime Kuma. Extend the MonitorType class and register your plugin to add new monitoring capabilities.

- Repository: [Louis Lam/uptime-kuma](https://github.com/louislam/uptime-kuma)
- Tags: how-to-guide
- Published: 2026-02-28

---

**Yes, you can create custom monitor type plugins for Uptime Kuma by extending the `MonitorType` base class, implementing the required `check` method, and registering your implementation in `UptimeKumaServer.monitorTypeList` located in [`server/uptime-kuma-server.js`](https://github.com/louislam/uptime-kuma/blob/main/server/uptime-kuma-server.js).**

Uptime Kuma is an open-source monitoring tool that exposes a class-based extension system for adding new monitoring capabilities. Whether you need to query a proprietary API or implement a specialized health check, you can build a custom monitor type that integrates natively with the existing UI and heartbeat engine without modifying core files beyond the registration step.

## Understanding the Monitor Type Architecture

Uptime Kuma’s monitoring engine relies on a registry pattern that maps string identifiers to instantiated monitor classes. The architecture consists of three primary layers:

- **`MonitorType` base class** ([`server/monitor-types/monitor-type.js`](https://github.com/louislam/uptime-kuma/blob/main/server/monitor-types/monitor-type.js)): Defines the contract for all monitor types, including the abstract `check` method and UI metadata properties like `name`, `type`, and `description`.
- **`UptimeKumaServer.monitorTypeList`** ([`server/uptime-kuma-server.js`](https://github.com/louislam/uptime-kuma/blob/main/server/uptime-kuma-server.js)): A global registry object that stores instantiated monitor types. The server constructor populates this list at startup.
- **Real-time UI synchronization** ([`server/client.js`](https://github.com/louislam/uptime-kuma/blob/main/server/client.js)): The `sendMonitorTypeList` function serializes the registry and emits it to connected clients via WebSocket, allowing the frontend ([`src/mixins/socket.js`](https://github.com/louislam/uptime-kuma/blob/main/src/mixins/socket.js)) to dynamically populate the "Add Monitor" dropdown without requiring static frontend builds.

When a heartbeat cycle executes, the server retrieves the monitor’s `type` string from the database, looks up the corresponding class in `monitorTypeList`, and invokes the `check` method with the monitor record and a fresh heartbeat object.

## Step-by-Step: Creating a Custom Monitor Plugin

### Step 1: Extend the MonitorType Base Class

Create a new file under `server/monitor-types/` that imports the base class and status constants. Every custom monitor must export a class that extends `MonitorType`.

```javascript
// server/monitor-types/custom-api.js
const { MonitorType } = require("./monitor-type");
const { UP, DOWN } = require("../../src/util");
const axios = require("axios");

class CustomApiMonitor extends MonitorType {
    name = "Custom API Check";
    type = "custom-api";
    description = "Monitor a custom REST endpoint with Bearer token authentication.";
    supportsConditions = true;
    conditionVariables = [
        { name: "responseTime", type: "number", label: "Response Time (ms)" }
    ];
    allowCustomStatus = false;
}

module.exports = { CustomApiMonitor };

```

### Step 2: Implement the Check Method

The `check` method is the only required override. It receives two arguments: the `monitor` object (containing database fields like `url` and `interval`) and the `heartbeat` object (which you populate with status, message, and timing data).

```javascript
async check(monitor, heartbeat) {
    const start = Date.now();
    
    try {
        const response = await axios.get(monitor.url, {
            headers: { "Authorization": `Bearer ${monitor.apiToken}` },
            timeout: monitor.timeout || 15000
        });
        
        const duration = Date.now() - start;
        
        if (response.status === 200) {
            heartbeat.status = UP;
            heartbeat.msg = "Service healthy";
            heartbeat.time = duration;
            
            // Expose variables for conditions if supportsConditions is true
            heartbeat.responseTime = duration;
        } else {
            throw new Error(`Unexpected status code: ${response.status}`);
        }
    } catch (error) {
        heartbeat.status = DOWN;
        heartbeat.msg = error.message || "Connection failed";
    }
}

```

**Key implementation details:**
- Set `heartbeat.status` to `UP`, `DOWN`, or `PENDING` (imported from [`src/util.js`](https://github.com/louislam/uptime-kuma/blob/main/src/util.js)).
- Set `heartbeat.time` to record response duration in milliseconds.
- If `allowCustomStatus` is `false` (default), the framework expects `UP` for success; any thrown error or `DOWN` status triggers a failure.
- Throwing an exception automatically results in a `DOWN` status if unhandled.

### Step 3: Register Your Monitor Type

Open [`server/uptime-kuma-server.js`](https://github.com/louislam/uptime-kuma/blob/main/server/uptime-kuma-server.js) and locate the constructor where `monitorTypeList` is populated. Import your class and instantiate it:

```javascript
const { CustomApiMonitor } = require("./monitor-types/custom-api");

// Inside the UptimeKumaServer constructor, after existing registrations:
UptimeKumaServer.monitorTypeList["custom-api"] = new CustomApiMonitor();

```

The string key (`"custom-api"`) must match the `type` property defined in your class. Once registered, the server automatically includes your monitor in the list sent to clients via `client.sendMonitorTypeList`.

### Step 4: Configure UI Behavior

Control how your monitor appears and behaves in the dashboard by setting these boolean and array properties:

- **`supportsConditions`**: Set to `true` if you want your monitor to appear in conditional logic (e.g., "alert when response time > 500ms").
- **`conditionVariables`**: An array of objects defining variables available for conditions. Each object requires `name`, `type` (`"number"` or `"string"`), and `label`.
- **`allowCustomStatus`**: Set to `true` only if your monitor sets non-standard status strings beyond `UP`/`DOWN`/`PENDING`.

If `supportsConditions` is `false`, the UI displays only standard fields (name, URL, interval) and omits condition configuration panels.

## Complete Working Example: HTTP Status Monitor

Here is a production-ready example that monitors a JSON endpoint and validates the response structure:

```javascript
// server/monitor-types/json-validator.js
const { MonitorType } = require("./monitor-type");
const { UP, DOWN } = require("../../src/util");
const axios = require("axios");

class JsonValidatorMonitor extends MonitorType {
    name = "JSON Validator";
    type = "json-validator";
    description = "Verify that a JSON endpoint returns expected schema fields.";
    supportsConditions = false;
    conditionVariables = [];
    allowCustomStatus = false;

    async check(monitor, heartbeat) {
        const startTime = Date.now();
        
        try {
            const res = await axios.get(monitor.url, {
                timeout: monitor.timeout || 10000,
                validateStatus: () => true // Handle status codes manually
            });
            
            heartbeat.time = Date.now() - startTime;
            
            if (res.status !== 200) {
                throw new Error(`HTTP ${res.status}`);
            }
            
            // Validate required JSON field exists
            if (!res.data || !res.data.status) {
                throw new Error("Missing 'status' field in JSON response");
            }
            
            if (res.data.status === "healthy") {
                heartbeat.status = UP;
                heartbeat.msg = "Schema valid and status healthy";
            } else {
                heartbeat.status = DOWN;
                heartbeat.msg = `Service reports status: ${res.data.status}`;
            }
        } catch (err) {
            heartbeat.status = DOWN;
            heartbeat.msg = err.message;
        }
    }
}

module.exports = { JsonValidatorMonitor };

```

Register this in [`server/uptime-kuma-server.js`](https://github.com/louislam/uptime-kuma/blob/main/server/uptime-kuma-server.js):

```javascript
const { JsonValidatorMonitor } = require("./monitor-types/json-validator");
UptimeKumaServer.monitorTypeList["json-validator"] = new JsonValidatorMonitor();

```

After restarting the Uptime Kuma server, "JSON Validator" appears immediately in the monitor type dropdown.

## Key Files for Plugin Development

- **[`server/monitor-types/monitor-type.js`](https://github.com/louislam/uptime-kuma/blob/main/server/monitor-types/monitor-type.js)**: The abstract base class defining the `check` method signature and UI metadata properties.
- **`server/monitor-types/*.js`** (e.g., [`tcp.js`](https://github.com/louislam/uptime-kuma/blob/main/tcp.js), [`dns.js`](https://github.com/louislam/uptime-kuma/blob/main/dns.js)): Reference implementations showing database interaction and heartbeat population patterns.
- **[`server/uptime-kuma-server.js`](https://github.com/louislam/uptime-kuma/blob/main/server/uptime-kuma-server.js)**: Contains the `monitorTypeList` registry where you must instantiate and register your plugin.
- **[`server/client.js`](https://github.com/louislam/uptime-kuma/blob/main/server/client.js)**: Implements `sendMonitorTypeList`, which serializes your monitor’s metadata for the frontend.
- **[`src/mixins/socket.js`](https://github.com/louislam/uptime-kuma/blob/main/src/mixins/socket.js)**: Frontend handler that receives the monitor type list and updates the UI state.
- **[`src/util.js`](https://github.com/louislam/uptime-kuma/blob/main/src/util.js)**: Exports status constants (`UP`, `DOWN`, `PENDING`) used to set heartbeat results.

## Summary

- **Extend `MonitorType`**: Create a new file in `server/monitor-types/` that inherits from the base class and implements the `async check(monitor, heartbeat)` method.
- **Register in `UptimeKumaServer.monitorTypeList`**: Import and instantiate your class in [`server/uptime-kuma-server.js`](https://github.com/louislam/uptime-kuma/blob/main/server/uptime-kuma-server.js) using a unique string key.
- **Set UI flags**: Configure `supportsConditions`, `conditionVariables`, and `allowCustomStatus` to control frontend behavior without modifying React components.
- **Return standard statuses**: Import `UP` and `DOWN` from [`src/util.js`](https://github.com/louislam/uptime-kuma/blob/main/src/util.js) and assign them to `heartbeat.status`, setting `heartbeat.time` for latency tracking.
- **Automatic UI integration**: The frontend receives new monitor types via WebSocket at runtime, so your custom type appears in the "Add Monitor" dialog immediately after server restart.

## Frequently Asked Questions

### Do I need to modify the frontend code to add a custom monitor type?

No. Uptime Kuma’s frontend receives the monitor type list dynamically through the WebSocket connection handled in [`src/mixins/socket.js`](https://github.com/louislam/uptime-kuma/blob/main/src/mixins/socket.js). As long as you register your class in `UptimeKumaServer.monitorTypeList` and set the appropriate metadata properties (`name`, `type`, `description`), the "Add Monitor" dropdown will automatically include your custom type. You only need frontend modifications if you require custom input fields beyond the standard URL, interval, and notification options.

### What methods are absolutely required when creating a monitor type?

You must implement only the **`check` method**. This async method accepts `monitor` (the database record) and `heartbeat` (the response object) as arguments. You must populate `heartbeat.status` with either `UP` or `DOWN` (constants from [`src/util.js`](https://github.com/louislam/uptime-kuma/blob/main/src/util.js)), and optionally set `heartbeat.msg` for the status message and `heartbeat.time` for response duration. The base class handles all other lifecycle management.

### How do I add custom condition variables for alerting logic?

Set **`supportsConditions = true`** in your class definition, then populate the **`conditionVariables`** array with objects containing `name`, `type` (`"number"` or `"string"`), and `label`. Inside your `check` method, assign values to the heartbeat object using these variable names (e.g., `heartbeat.responseTime = duration`). The UI will then allow users to create rules like "alert when responseTime > 500" without additional frontend code.

### Can I use third-party npm packages in my custom monitor?

Yes. Since custom monitor types are standard Node.js modules loaded by [`server/uptime-kuma-server.js`](https://github.com/louislam/uptime-kuma/blob/main/server/uptime-kuma-server.js), you can `require()` any package available in the project’s `node_modules` or install new dependencies. Ensure you handle exceptions properly within your `check` method to prevent unhandled promise rejections, as errors thrown will result in a `DOWN` status unless caught and handled manually.