HTTP Interface

```
\r\n
__exception__\r\n
<TAG>\r\n
<error message>\r\n
<message_length> <TAG>\r\n
__exception__\r\n
```

Where `<TAG>` is a 16 byte random tag, which is the same tag sent in the `X-ClickHouse-Exception-Tag` response header.
The `<error message>` is the actual exception message (exact length can be found in `<message_length>`). The whole exception block described above can be up to 16 KiB.

Here is an example in `JSON` format

```
$ curl -v -Ss "http://localhost:8123/?max_block_size=1&query=select+sleepEachRow(0.001),throwIf(number=2)from+numbers(5)+FORMAT+JSON"
...
{
    "meta":
    [
        {
            "name": "sleepEachRow(0.001)",
            "type": "UInt8"
        },
        {
            "name": "throwIf(equals(number, 2))",
            "type": "UInt8"
        }
    ],

    "data":
    [
        {
            "sleepEachRow(0.001)": 0,
            "throwIf(equals(number, 2))": 0
        },
        {
            "sleepEachRow(0.001)": 0,
            "throwIf(equals(number, 2))": 0
        }
__exception__
dmrdfnujjqvszhav
Code: 395. DB::Exception: Value passed to 'throwIf' function is non-zero: while executing 'FUNCTION throwIf(equals(__table1.number, 2_UInt8) :: 1) -> throwIf(equals(__table1.number, 2_UInt8)) UInt8 : 0'. (FUNCTION_THROW_IF_VALUE_IS_NON_ZERO) (version 25.11.1.1)
262 dmrdfnujjqvszhav
__exception__
```

Here is similar example but in `CSV` format

```
$ curl -v -Ss "http://localhost:8123/?max_block_size=1&query=select+sleepEachRow(0.001),throwIf(number=2)from+numbers(5)+FORMAT+CSV"
...
<
0,0
0,0

__exception__
rumfyutuqkncbgau
Code: 395. DB::Exception: Value passed to 'throwIf' function is non-zero: while executing 'FUNCTION throwIf(equals(__table1.number, 2_UInt8) :: 1) -> throwIf(equals(__table1.number, 2_UInt8)) UInt8 : 0'. (FUNCTION_THROW_IF_VALUE_IS_NON_ZERO) (version 25.11.1.1)
262 rumfyutuqkncbgau
__exception__
```

## Queries with parameters[​](#cli-queries-with-parameters "Direct link to Queries with parameters")

You can create a query with parameters and pass values for them from the corresponding HTTP request parameters. For more information, see [Queries with Parameters for CLI](/docs/interfaces/client#cli-queries-with-parameters).

### Example[​](#example-3 "Direct link to Example")

```
$ curl -sS "<address>?param_id=2&param_phrase=test" -d "SELECT * FROM table WHERE int_column = {id:UInt8} and string_column = {phrase:String}"
```

### Tabs in URL Parameters[​](#tabs-in-url-parameters "Direct link to Tabs in URL Parameters")

Query parameters are parsed from the "escaped" format. This has some benefits, such as the possibility to unambiguously parse nulls as `\N`. This means the tab character should be encoded as `\t` (or `\` and a tab). For example, the following contains an actual tab between `abc` and `123` and the input string is split into two values:

```
curl -sS "http://localhost:8123" -d "SELECT splitByChar('\t', 'abc      123')"
```

```
['abc','123']
```

However, if you try to encode an actual tab using `%09` in a URL parameter, it won't get parsed properly:

```
curl -sS "http://localhost:8123?param_arg1=abc%09123" -d "SELECT splitByChar('\t', {arg1:String})"
Code: 457. DB::Exception: Value abc    123 cannot be parsed as String for query parameter 'arg1' because it isn't parsed completely: only 3 of 7 bytes was parsed: abc. (BAD_QUERY_PARAMETER) (version 23.4.1.869 (official build))
```

If you're using URL parameters, you will need to encode the `\t` as `%5C%09`. For example:

```
curl -sS "http://localhost:8123?param_arg1=abc%5C%09123" -d "SELECT splitByChar('\t', {arg1:String})"
```

```
['abc','123']
```

## Predefined HTTP Interface[​](#predefined_http_interface "Direct link to Predefined HTTP Interface")

ClickHouse supports specific queries through the HTTP interface. For example, you can write data to a table as follows:

```
$ echo '(4),(5),(6)' | curl 'http://localhost:8123/?query=INSERT%20INTO%20t%20VALUES' --data-binary @-
```

ClickHouse also supports a Predefined HTTP Interface which can help you more easily integrate with third-party tools like [Prometheus exporter](https://github.com/ClickHouse/clickhouse_exporter). Let's look at an example.

First of all, add this section to your server configuration file.

`http_handlers` is configured to contain multiple `rule`. ClickHouse will match the HTTP requests received to the predefined type in `rule` and the first rule matched runs the handler. Then ClickHouse will execute the corresponding predefined query if the match is successful.

```
<http_handlers>
    <rule>
        <url>/predefined_query</url>
        <methods>POST,GET</methods>
        <handler>
            <type>predefined_query_handler</type>
            <query>SELECT * FROM system.metrics LIMIT 5 FORMAT Template SETTINGS format_template_resultset = 'prometheus_template_output_format_resultset', format_template_row = 'prometheus_template_output_format_row', format_template_rows_between_delimiter = '\n'</query>
        </handler>
    </rule>
    <rule>...</rule>
    <rule>...</rule>
</http_handlers>
```

You can now request the URL directly for data in the Prometheus format:

```
$ curl -v 'http://localhost:8123/predefined_query'
*   Trying ::1...
* Connected to localhost (::1) port 8123 (#0)
> GET /predefined_query HTTP/1.1
> Host: localhost:8123
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Tue, 28 Apr 2020 08:52:56 GMT
< Connection: Keep-Alive
< Content-Type: text/plain; charset=UTF-8
< X-ClickHouse-Server-Display-Name: i-mloy5trc
< Transfer-Encoding: chunked
< X-ClickHouse-Query-Id: 96fe0052-01e6-43ce-b12a-6b7370de6e8a
< X-ClickHouse-Format: Template
< X-ClickHouse-Timezone: Asia/Shanghai
< Keep-Alive: timeout=10
< X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0","elapsed_ns":"662334","memory_usage":"8451671"}
<
# HELP "Query" "Number of executing queries"
# TYPE "Query" counter
"Query" 1

# HELP "Merge" "Number of executing background merges"
# TYPE "Merge" counter
"Merge" 0

# HELP "PartMutation" "Number of mutations (ALTER DELETE/UPDATE)"
# TYPE "PartMutation" counter
"PartMutation" 0

# HELP "ReplicatedFetch" "Number of data parts being fetched from replica"
# TYPE "ReplicatedFetch" counter
"ReplicatedFetch" 0

# HELP "ReplicatedSend" "Number of data parts being sent to replicas"
# TYPE "ReplicatedSend" counter
"ReplicatedSend" 0

* Connection #0 to host localhost left intact

* Connection #0 to host localhost left intact
```

Configuration options for `http_handlers` work as follows.

`rule` can configure the following parameters:

- `method`
- `headers`
- `url`
- `full_url`
- `handler`

Each of these are discussed below:

- `method` is responsible for matching the method part of the HTTP request. `method` fully conforms to the definition of [`method`]  
  (<https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods>) in the HTTP protocol. It is an optional configuration. If it isn't defined in the  
  configuration file, it doesn't match the method portion of the HTTP request.
- `url` is responsible for matching the URL part (path and query string) of the HTTP request.
  If the `url` prefixed with `regex:` it expects [RE2](https://github.com/google/re2)'s regular expressions.
  It is an optional configuration. If it isn't defined in the configuration file, it doesn't match the URL portion of the HTTP request.
- `full_url` same as `url`, but, includes complete URL, i.e. `schema://host:port/path?query_string`.
  Note, ClickHouse doesn't support "virtual hosts", so the `host` is an IP address (and not the value of `Host` header).
- `empty_query_string` - ensures that there is no query string (`?query_string`) in the request
- `headers` are responsible for matching the header part of the HTTP request. It is compatible with RE2's regular expressions. It is an optional
  configuration. If it isn't defined in the configuration file, it doesn't match the header portion of the HTTP request.
- `handler` contains the main processing part.

  It can have the following `type`: