How API Authentication and Rate Limiting Work in Uptime Kuma

Uptime Kuma protects its HTTP API using API keys (or basic auth fallback) and enforces per-endpoint rate limits via token-bucket limiters to prevent abuse.

The louislam/uptime-kuma repository implements a dual-layer security model that combines flexible authentication with aggressive throttling. Understanding how server/auth.js and server/rate-limiter.js interact is essential for integrating monitoring data safely into your infrastructure. This article explains the exact mechanisms governing credential verification and request throttling as implemented in the source code.

API Authentication Architecture

Authentication Flow and Middleware

All API routes in Uptime Kuma are protected by the apiAuth middleware defined in server/auth.js. The middleware first consults runtime settings to determine which authentication mode is active:

  1. Auth disabled mode – When Settings.get("disableAuth") returns true, the middleware bypasses all checks entirely (useful for isolated testing environments).
  2. API key mode – When apiKeysEnabled is true, the system invokes apiAuthorizer (lines 79-96 in server/auth.js).
  3. Basic auth fallback – If API keys are disabled, the system falls back to userAuthorizer (lines 106-122 in server/auth.js) for traditional username/password validation.

Both authorizers integrate with the rate limiting system before performing credential verification. If the respective rate limiter denies the request, authentication aborts immediately and logs a warning.

API Key Format and Verification

Uptime Kuma API keys follow a strict format: uk<ID>_<secret>. The prefix uk identifies the key type, the numeric segment between the prefix and the first underscore represents the database ID, and the trailing segment is the clear-text secret users must protect.

The verification logic resides in verifyAPIKey (lines 41-63 in server/auth.js). This function:

  • Extracts the ID from the key format
  • Queries the api_key table for the stored bcrypt hash
  • Validates the key's expiry date and active status
  • Compares the supplied clear-text secret against the stored hash using passwordHash

When authentication succeeds, the request proceeds to the route handler. On failure, the server returns 401 Unauthorized. Notably, rate limiter tokens are not consumed for failed API key validations—only successful checks decrement the bucket.

Basic Auth Fallback

When API keys are disabled, userAuthorizer handles credential validation using the same HTTP Basic Auth mechanism but validates against user account passwords stored in the database. This path uses loginRateLimiter rather than apiRateLimiter, applying stricter throttling appropriate for interactive login attempts.

Rate Limiting Implementation

Token Bucket Configuration

Uptime Kuma leverages the limiter NPM package to implement token-bucket rate limiting. The server/rate-limiter.js file instantiates three independent limiters wrapped in a custom KumaRateLimiter class that logs remaining tokens via its pass() method (lines 25-38).

Each limiter maintains a token count that decrements with every permitted request. When the count goes negative, the limiter returns false and the calling authorizer rejects the request.

Rate Limit Thresholds

The system enforces distinct thresholds for different authentication surfaces:

  • apiRateLimiter: 60 requests per minute for API key authentication (apiAuthorizer)
  • loginRateLimiter: 20 requests per minute for username/password login attempts (userAuthorizer)
  • twoFaRateLimiter: 30 requests per minute for two-factor authentication verification (handled in 2fa.js)

These limits apply before credential verification occurs, protecting the bcrypt hashing operations from brute-force load.

Runtime Configuration Settings

Authentication behavior is controlled through the Settings class in server/settings.js, which provides a cached key/value store with a 60-second TTL:

  • disableAuth: When set to true, all authentication checks are skipped across the entire application
  • apiKeysEnabled: Toggles between API key mode and traditional basic authentication

Both settings persist in the setting database table and are queried by apiAuth on every request to determine which authorization path to execute.

Practical Usage Examples

Creating API Keys

Generate keys through the web interface:

  1. Log in to the Uptime Kuma dashboard
  2. Navigate to Settings → API Keys
  3. Click Add New Key to generate a key like uk12_7e4a9b...
  4. Copy the key immediately—the clear-text secret cannot be retrieved later

The UI stores only the bcrypt hash in the api_key table via the socket handler in server/socket-handlers/api-key-socket-handler.js.

Authenticating Requests with cURL

Pass the API key as the password in HTTP Basic Auth. The username field is ignored but conventionally set to api:

curl -u api:'uk12_7e4a9b...' \
     -H "Accept: application/json" \
     https://uptime.kuma.example/api/monitors

For automated scripts, include the key in the Authorization header:

curl -H "Authorization: Basic $(echo -n 'api:uk12_7e4a9b...' | base64)" \
     https://uptime.kuma.example/api/monitors

Handling Rate Limit Responses

When exceeding the 60 requests/minute threshold for API keys, the apiRateLimiter causes apiAuthorizer to return 401 Unauthorized (or 429 Too Many Requests in some edge cases). Test rate limiting behavior with a loop:

for i in {1..65}; do
  curl -s -o /dev/null -w "%{http_code}\n" \
       -u api:'uk12_7e4a9b...' \
       https://uptime.kuma.example/api/monitors
done

Requests 61 through 65 will fail with authentication errors once the token bucket empties.

Summary

  • API authentication in Uptime Kuma uses the apiAuth middleware to choose between API key verification (apiAuthorizer) and basic auth (userAuthorizer) based on the apiKeysEnabled setting.
  • API keys follow the format uk<ID>_<secret> and are verified against bcrypt hashes stored in the database via verifyAPIKey in server/auth.js.
  • Rate limiting employs token-bucket limiters (apiRateLimiter, loginRateLimiter, twoFaRateLimiter) that enforce thresholds of 60, 20, and 30 requests per minute respectively.
  • Runtime settings (disableAuth, apiKeysEnabled) are cached for 60 seconds via server/settings.js to minimize database queries on every request.
  • Security sequencing checks rate limits before performing expensive bcrypt hash comparisons, preventing CPU exhaustion attacks.

Frequently Asked Questions

What authentication methods does Uptime Kuma support?

Uptime Kuma supports two primary authentication methods: API keys (recommended for automation) and HTTP Basic Auth using username and password credentials. The active method is determined by the apiKeysEnabled runtime setting stored in server/settings.js. When disableAuth is enabled, all authentication is bypassed for testing purposes.

How does the API key format work in Uptime Kuma?

All API keys use the format uk<ID>_<secret>, where the numeric ID identifies the database record and the secret portion is user-provided. The server extracts the ID from between the uk prefix and the first underscore, then verifies the secret against a bcrypt hash stored in the api_key table using the verifyAPIKey function in server/auth.js.

What are the rate limits for API requests?

Uptime Kuma enforces three distinct rate limits via server/rate-limiter.js: 60 requests per minute for API key authentication (apiRateLimiter), 20 requests per minute for username/password login attempts (loginRateLimiter), and 30 requests per minute for 2FA verification (twoFaRateLimiter). These limits apply before credential validation to protect against brute-force attacks.

How can I disable authentication for testing?

Set the disableAuth setting to true via the runtime configuration in server/settings.js. When this flag is active, the apiAuth middleware in server/auth.js bypasses all credential checks, allowing unrestricted access to the API. This should only be used in isolated testing environments and never in production deployments.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →