HTTP Interface

[Edit this page](https://github.com/ClickHouse/clickhouse-docs/blob/main/docs/integrations/interfaces/http.md)

## Prerequisites[​](#prerequisites "Direct link to Prerequisites")

For the examples in this article you will need:

- to have a running instance of ClickHouse server
- have `curl` installed. On Ubuntu or Debian, run `sudo apt install curl` or refer to this [documentation](https://curl.se/download.html) for installation instructions.

## Overview[​](#overview "Direct link to Overview")

The HTTP interface lets you use ClickHouse on any platform from any programming language in the form of a REST API. The HTTP interface is more limited than the native interface, but it has better language support.

By default, `clickhouse-server` listens on the following ports:

- port 8123 for HTTP
- port 8443 for HTTPS can be enabled

If you make a `GET /` request without any parameters, a 200 response code is returned along with the string "Ok.":

```
$ curl 'http://localhost:8123/'
Ok.
```

"Ok." is the default value defined in [`http_server_default_response`](/docs/operations/server-configuration-parameters/settings#http_server_default_response) and can be changed if desired.

Also see: [HTTP response codes caveats](#http_response_codes_caveats).

## Web user interface[​](#web-ui "Direct link to Web user interface")

ClickHouse includes a web user interface, which can be accessed from the following address:

```
http://localhost:8123/play
```

The web UI supports displaying progress during query runtime, query cancellation, and result streaming.
It has a secret feature for displaying charts and graphs for query pipelines.

After executing a query successfully, a download button appears that allows you to download the query results in various formats including CSV, TSV, JSON, JSONLines, Parquet, Markdown, or any custom format supported by ClickHouse. The download feature uses the query cache to efficiently retrieve results without re-executing the query. It will download the full result set even if the UI displayed only a single page out of many.

The web UI is designed for professionals like you.

In health-check scripts use the `GET /ping` request. This handler always returns "Ok." (with a line feed at the end). Available from version 18.12.13. See also `/replicas_status` to check replica's delay.

```
$ curl 'http://localhost:8123/ping'
Ok.
$ curl 'http://localhost:8123/replicas_status'
Ok.
```

## Querying over HTTP/HTTPS[​](#querying "Direct link to Querying over HTTP/HTTPS")

To query over HTTP/HTTPS there are three options:

- send the request as a URL 'query' parameter
- using the POST method.
- Send the beginning of the query in the 'query' parameter, and the rest using POST

Note

The size of the URL is limited to 1 MiB by default, this can be changed with the `http_max_uri_size` setting.

If successful, you receive the 200 response code and the result in the response body.
If an error occurs, you receive the 500 response code and an error description text in the response body.

Requests using GET are 'readonly'. This means that for queries that modify data, you can only use the POST method.
You can send the query itself either in the POST body or in the URL parameter. Let's look at some examples.

In the example below curl is used to send the query `SELECT 1`. Note the use of URL encoding for the space: `%20`.

```
curl 'http://localhost:8123/?query=SELECT%201'
```

```
1
```

In this example wget is used with the `-nv` (non-verbose) and `-O-` parameters to output the result to the terminal.
In this case it isn't necessary to use URL encoding for the space:

```
wget -nv -O- 'http://localhost:8123/?query=SELECT 1'
```

```
1
```

In this example we pipe a raw HTTP request into netcat:

```
echo -ne 'GET /?query=SELECT%201 HTTP/1.0\r\n\r\n' | nc localhost 8123
```

```
HTTP/1.0 200 OK
X-ClickHouse-Summary: {"read_rows":"1","read_bytes":"1","written_rows":"0","written_bytes":"0","total_rows_to_read":"1","result_rows":"0","result_bytes":"0","elapsed_ns":"4505959","memory_usage":"1111711"}
Date: Tue, 11 Nov 2025 18:16:01 GMT
Connection: Close
Content-Type: text/tab-separated-values; charset=UTF-8
Access-Control-Expose-Headers: X-ClickHouse-Query-Id,X-ClickHouse-Summary,X-ClickHouse-Server-Display-Name,X-ClickHouse-Format,X-ClickHouse-Timezone,X-ClickHouse-Exception-Code,X-ClickHouse-Exception-Tag
X-ClickHouse-Server-Display-Name: MacBook-Pro.local
X-ClickHouse-Query-Id: ec0d8ec6-efc4-4e1d-a14f-b748e01f5294
X-ClickHouse-Format: TabSeparated
X-ClickHouse-Timezone: Europe/London
X-ClickHouse-Exception-Tag: dngjzjnxkvlwkeua

1
```

As you can see, the `curl` command is somewhat inconvenient in that spaces must be URL escaped.
Although `wget` escapes everything itself, we don't recommend using it because it doesn't work well over HTTP 1.1 when using keep-alive and Transfer-Encoding: chunked.

```
$ echo 'SELECT 1' | curl 'http://localhost:8123/' --data-binary @-
1

$ echo 'SELECT 1' | curl 'http://localhost:8123/?query=' --data-binary @-
1

$ echo '1' | curl 'http://localhost:8123/?query=SELECT' --data-binary @-
1
```

If part of the query is sent in the parameter, and part in the POST, a line feed is inserted between these two data parts.
For example, this won't work:

```
$ echo 'ECT 1' | curl 'http://localhost:8123/?query=SEL' --data-binary @-
Code: 59, e.displayText() = DB::Exception: Syntax error: failed at position 0: SEL
ECT 1
, expected One of: SHOW TABLES, SHOW DATABASES, SELECT, INSERT, CREATE, ATTACH, RENAME, DROP, DETACH, USE, SET, OPTIMIZE., e.what() = DB::Exception
```

By default, data is returned in the [`TabSeparated`](/docs/interfaces/formats/TabSeparated) format.

The `FORMAT` clause is used in the query to request any other format. For example:

```
wget -nv -O- 'http://localhost:8123/?query=SELECT 1, 2, 3 FORMAT JSON'
```

```
{
    "meta":
    [
        {
            "name": "1",
            "type": "UInt8"
        },
        {
            "name": "2",
            "type": "UInt8"
        },
        {
            "name": "3",
            "type": "UInt8"
        }
    ],

    "data":
    [
        {
            "1": 1,
            "2": 2,
            "3": 3
        }
    ],

    "rows": 1,

    "statistics":
    {
        "elapsed": 0.000515,
        "rows_read": 1,
        "bytes_read": 1
    }
}
```

You can use the `default_format` URL parameter or the `X-ClickHouse-Format` header to specify a default format other than `TabSeparated`.

```
$ echo 'SELECT 1 FORMAT Pretty' | curl 'http://localhost:8123/?' --data-binary @-
┏━━━┓
┃ 1 ┃
┡━━━┩
│ 1 │
└───┘
```

You can use POST method with parameterized queries. The parameters are specified using curly braces with the parameter name and type, like `{name:Type}`. The parameter values are passed with the `param_name`:

```
$ curl -X POST -F 'query=select {p1:UInt8} + {p2:UInt8}' -F "param_p1=3" -F "param_p2=4" 'http://localhost:8123/'

7
```

## Insert queries over HTTP/HTTPS[​](#insert-queries "Direct link to Insert queries over HTTP/HTTPS")

The `POST` method of transmitting data is necessary for `INSERT` queries. In this case, you can write the beginning of the query in the URL parameter, and use POST to pass the data to insert. The data to insert could be, for example, a tab-separated dump from MySQL. In this way, the `INSERT` query replaces `LOAD DATA LOCAL INFILE` from MySQL.

### Examples[​](#examples "Direct link to Examples")

To create a table:

```
$ echo 'CREATE TABLE t (a UInt8) ENGINE = Memory' | curl 'http://localhost:8123/' --data-binary @-
```

To use the familiar `INSERT` query for data insertion:

```
$ echo 'INSERT INTO t VALUES (1),(2),(3)' | curl 'http://localhost:8123/' --data-binary @-
```

To send data separately from the query:

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

Any data format can be specified. For example, the 'Values' format, the same format as the one used when writing `INSERT INTO t VALUES`, can be specified:

```
$ echo '(7),(8),(9)' | curl 'http://localhost:8123/?query=INSERT%20INTO%20t%20FORMAT%20Values' --data-binary @-
```