The ClickHouse HTTP interface ships with several built-in endpoints, including /, /ping, /replicas_status, and /play. The <http_handlers> configuration section lets you add custom routes, restrict existing ones, or serve predefined queries through a clean URL. This is the same machinery that powers features such as remote jemalloc pprof endpoints and lightweight REST-style APIs in front of ClickHouse.
Where Handlers Are Defined
HTTP handlers live in the server config, typically under /etc/clickhouse-server/config.d/. Each rule matches an incoming request by URL and method, then dispatches it to a handler. If you define <http_handlers> without <defaults/>, the built-in routes disappear, so almost every real config includes <defaults/> to keep /ping, /replicas_status, and the query interface working.
<?xml version="1.0" ?>
<clickhouse>
<http_handlers>
<rule>
<url>/custom</url>
<methods>GET,POST</methods>
<handler>
<type>predefined_query_handler</type>
<query>SELECT 1</query>
</handler>
</rule>
<defaults/>
</http_handlers>
</clickhouse>
Handler Types
| Type | Purpose |
|---|---|
dynamic_query_handler |
Accepts a query parameter from the URL or body, like the default / endpoint |
predefined_query_handler |
Runs a fixed SQL statement embedded in the config |
static |
Returns a static response with a configured status, content type, and body |
The static type is what you use to disable an endpoint by returning 403, redirect traffic, or serve a health page that does not run SQL.
Example: Disable the /play UI
The web SQL console at /play is convenient in development but is often unwanted on production servers facing untrusted networks. A static handler returning 403 shuts it off without disabling the HTTP interface:
<?xml version="1.0" ?>
<clickhouse>
<http_handlers>
<rule>
<url>/play</url>
<methods>GET</methods>
<handler>
<type>static</type>
<status>403</status>
<content_type>text/plain; charset=UTF-8</content_type>
<response_content></response_content>
</handler>
</rule>
<defaults/>
</http_handlers>
</clickhouse>
The <defaults/> tag preserves /, /ping, and the rest, so the rule only affects /play.
Example: Predefined Query Endpoint
Expose a curated query as a stable URL. Callers do not need to know the schema and cannot inject arbitrary SQL:
<rule>
<url>/api/active_queries</url>
<methods>GET</methods>
<handler>
<type>predefined_query_handler</type>
<query>
SELECT query_id, user, elapsed, read_rows
FROM system.processes
FORMAT JSON
</query>
</handler>
</rule>
A simple curl http://clickhouse:8123/api/active_queries returns the JSON response.
Key Configuration Elements
<url>matches the request path. Regex syntax is allowed when the value starts withregex:.<methods>is a comma-separated list of HTTP verbs.<handler>defines the response. Each type has its own required sub-elements.<headers>(optional) can match specific request headers, useful for routing byContent-Type.<empty_query_string/>enforces that no query is passed alongside a predefined handler.
Common Pitfalls
- Omitting
<defaults/>and accidentally disabling/ping, breaking health checks and load balancer probes. - Putting custom rules after
<defaults/>. Order matters and the first match wins, so specific rules must come first. - Using
predefined_query_handlerwith user-supplied parameters but noparam_namevalidation, which can still allow SQL injection through substitutions. - Forgetting that handlers run as the authenticated user. Apply
readonlyprofiles for endpoints exposed externally.
Frequently Asked Questions
Q: Can I serve different ClickHouse queries from the same hostname based on path?
A: Yes, that is exactly what http_handlers is for. Define one <rule> per path with a predefined_query_handler.
Q: How do I keep the default endpoints working when I add custom rules?
A: Include <defaults/> at the end of the <http_handlers> block. Without it, only your custom rules respond.
Q: Can I require authentication for custom handlers? A: Yes. Handlers reuse the standard HTTP authentication path. Use a dedicated read-only user with a restricted profile.
Q: Does static support files from disk?
A: It can return inline content or a file path via <response_content>file://...</response_content>. Keep these files small, since they are served by the ClickHouse process.
Q: What is the difference between dynamic_query_handler and the default /?
A: The default / already behaves like a dynamic handler. You only need to define one explicitly when you want to change the parameter name or constrain it to a specific URL.