Requests functions in the HTTP Client DuckDB extension
Function category
Requests
4 functionsIssue HTTP requests from DuckDB SQL. [`http_get`](#http_get) for reads, [`http_post`](#http_post) for JSON-body POSTs, [`http_post_form`](#http_post_form) for `application/x-www-form-urlencoded` POSTs. Each returns a JSON object with `status`, `reason`, and `body`.
Signature
Arguments (Positional)
| Argument | Type | Mode | Description |
|---|---|---|---|
Argument
url
|
Type
VARCHAR
|
Mode Positional |
Description
The URL to fetch. Must include the scheme — https://... or http://....
|
Returns
A JSON object with status (the HTTP status code as a number), reason (the HTTP reason phrase, e.g. "OK" / "Not Found"), and body (the response body as a string).
Description
Issue an HTTP GET against url and return the response as JSON. Synchronous — DuckDB blocks until the response arrives or the request fails.
Extract fields from the result with DuckDB's JSON operators: ->> for string fields, -> for nested JSON. To dive into a JSON response body, cast it: ((http_get(...)->>'body')::JSON)->>'$.field'.
For REST endpoints that need headers (auth tokens, content negotiation), use http_post instead — http_get does not currently expose a headers parameter in the documented signature.
SELECT (http_get('https://httpbin.org/get')->>'status')::INT AS status;
WITH r AS (
SELECT http_get('https://httpbin.org/uuid') AS res
)
SELECT ((res->>'body')::JSON)->>'$.uuid' AS uuid
FROM r;
SELECT u.id,
u.email,
((http_get('https://api.example.com/score/' || u.id::VARCHAR)->>'body')::JSON)->>'$.score' AS score
FROM users u
WHERE u.last_seen > now() - INTERVAL 1 HOUR
LIMIT 100;
Signature
Arguments (Positional)
| Argument | Type | Mode | Description |
|---|---|---|---|
Argument
url
|
Type
VARCHAR
|
Mode Positional |
Description
The URL to issue the HEAD request against.
|
Returns
A JSON object with the same status / reason / body shape as http_get. For a well-behaved server the body is empty.
Description
Issue an HTTP HEAD request — same response metadata as a GET, but without a body. Use it for liveness checks or to test whether a URL exists before fetching the full payload with http_get.
This function is exposed by the extension binary but is not documented in the upstream README — the signature could change in a future release. Treat it as best-effort.
SELECT (http_head('https://httpbin.org/')->>'status')::INT AS status;
Signature
Arguments
| Argument | Type | Mode | Description |
|---|---|---|---|
Argument
url
|
Type
VARCHAR
|
Mode Positional | Description The URL to POST to. |
Argument
headers
|
Type
MAP(VARCHAR, VARCHAR)
|
Mode Named |
Description
Request headers as a MAP — MAP{'authorization': 'Bearer ...', 'content-type': 'application/json'}. Sent on the wire as-is.
|
Argument
params
|
Type
MAP(VARCHAR, VARCHAR)
|
Mode Named |
Description
Body parameters as a MAP. JSON-encoded into the request body — keys become object keys, values become JSON string values.
|
Returns
A JSON object with status, reason, and body — same shape as http_get.
Description
Issue an HTTP POST with the params map JSON-encoded as the request body. Use this for REST APIs that consume JSON; pair it with headers => MAP{'content-type': 'application/json'} so the server knows to parse the body as JSON.
For application/x-www-form-urlencoded bodies (older REST APIs, OAuth token endpoints, HTML form handlers), use http_post_form instead.
Keep credentials out of cached query plans by binding them through SET VARIABLE + getenv — see Securing credentials.
SELECT http_post(
'https://httpbin.org/post',
headers => MAP{'accept': 'application/json',
'content-type': 'application/json'},
params => MAP{'name': 'alice', 'plan': 'pro'}
);
SET VARIABLE api_token = getenv('API_TOKEN');
SELECT http_post(
'https://api.example.com/users',
headers => MAP{
'authorization': 'Bearer ' || :api_token,
'content-type': 'application/json'
},
params => MAP{'email': '[email protected]'}
);
SELECT (http_post('https://httpbin.org/post',
headers => MAP{},
params => MAP{'k': 'v'})->>'status')::INT AS status;
Signature
Arguments
| Argument | Type | Mode | Description |
|---|---|---|---|
Argument
url
|
Type
VARCHAR
|
Mode Positional | Description The URL to POST to. |
Argument
headers
|
Type
MAP(VARCHAR, VARCHAR)
|
Mode Named |
Description
Request headers as a MAP. Pass MAP{} if you don't need any.
|
Argument
params
|
Type
MAP(VARCHAR, VARCHAR)
|
Mode Named |
Description
Form fields as a MAP. Each entry is URL-encoded into the request body using application/x-www-form-urlencoded.
|
Returns
A JSON object with status, reason, and body — same shape as http_get.
Description
Issue an HTTP POST with the params map encoded as application/x-www-form-urlencoded — the body shape used by HTML forms, many older REST APIs, and OAuth 2.0 token endpoints.
The extension sets the request's Content-Type header to application/x-www-form-urlencoded for you; you don't need to put it in headers manually.
For JSON request bodies, use http_post instead.
SELECT http_post_form(
'https://httpbin.org/post',
headers => MAP{},
params => MAP{'limit': '10', 'cursor': 'abc'}
);
SET VARIABLE client_id = getenv('OAUTH_CLIENT_ID');
SET VARIABLE client_secret = getenv('OAUTH_CLIENT_SECRET');
SELECT ((http_post_form(
'https://oauth.example.com/token',
headers => MAP{},
params => MAP{
'grant_type': 'client_credentials',
'client_id': :client_id,
'client_secret': :client_secret
}
)->>'body')::JSON)->>'$.access_token' AS access_token;