Build a curl command from an HTTP request
Turn a structured HTTP request into a curl command that is ready to paste into a POSIX-compatible shell.
Run — free
Supply the method, an absolute URL, any headers, and an optional text body. The builder quotes every dynamic value, including spaces, query strings, punctuation, and embedded apostrophes, so the shell does not reinterpret request data as syntax. It is useful for debugging APIs, reproducing requests from logs, writing documentation, and handing an exact request to another developer without manually assembling flags.
Describe the request you want to reproduce
Start with the HTTP method and the complete URL. The URL must be absolute, which means it includes a scheme such as HTTPS and enough information for curl to locate the destination without relying on browser context or a base address. Add headers as ordered name-and-value rows when the request needs authorization, content negotiation, tracing, conditional behavior, or a declared content type. Add the body only when the request carries one; an empty string is treated as an intentional empty body, while an omitted body adds no data flag. The resulting command uses an explicit method flag, followed by the quoted URL, one header flag for every supplied row, and a raw data flag when a body is present. Header order is preserved, making the output easy to compare with a captured request or a test fixture. The builder does not send anything, resolve the host, inspect credentials, or change the payload. It only converts the values you provide into a deterministic command line.
Understand how shell quoting protects each value
A command line is interpreted by a shell before curl receives it, so copying request values without quoting can silently change their meaning. Ampersands in query strings can start background commands, dollar signs can trigger expansion, spaces can split one value into several arguments, and quotes inside JSON can become shell syntax. This builder wraps every dynamic argument in POSIX single quotes. When a value itself contains an apostrophe, it closes the quoted section, inserts a literal apostrophe through a double-quoted fragment, and resumes the single-quoted section. That familiar sequence looks unusual, but it preserves the exact bytes of the original string in shells such as sh, bash, dash, and zsh. Headers are emitted as a single quoted argument containing the name, a colon, a space, and the value. Bodies use curl's raw data option so an initial at-sign is not interpreted as a filename. The result targets POSIX-style shells; PowerShell and Windows Command Prompt have different quoting rules and should not be assumed to interpret this output identically.
Validate the result before sharing or running it
The builder rejects a missing or relative URL because a fragment such as /users/42 is ambiguous outside the application that supplied its base address. It also validates the method as an HTTP token, checks header names against the token syntax, requires string header values, and rejects line breaks in those values. These checks prevent malformed request structure from being disguised by otherwise correct shell quoting. They do not decide whether a server supports a method, whether a URL points to the intended environment, or whether a credential is safe to disclose. Review the generated command before running it, especially when it contains authorization headers, session cookies, personal data, or a production hostname. Prefer short-lived test credentials in documentation and issue reports, and redact secrets before sending a command through chat or a ticket. Because generation is deterministic, the same structured input always produces the same text. That makes the result suitable for snapshots, developer documentation, reproducible bug reports, and code-review discussions where small request changes need to remain visible.
What you can do with it
Reproduce an API failure
Convert the method, URL, headers, and captured body into a pasteable command for local debugging.
Write accurate API documentation
Generate consistent curl examples without manually escaping JSON, query parameters, or header values.
Share a request with a teammate
Provide one deterministic command that preserves the request structure while making changes easy to review.
FAQ
What does it cost?
The browser tool is free to use. API execution costs $0.002 per request.
Does this tool send the HTTP request?
No. It only builds command-line text and performs no network access.
Why must the URL be absolute?
A relative URL depends on an unstated base address, so it cannot represent a complete standalone curl request.
How are apostrophes handled?
Each apostrophe is encoded by ending the single-quoted section, inserting a literal apostrophe, and reopening the section.
Can I use the result in PowerShell?
The output is designed for POSIX-compatible shells. PowerShell applies different parsing and quoting rules.
Are secrets removed from headers?
No. Values are preserved exactly, so you should redact credentials before sharing the generated command.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/dev2/curl-command-build \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"method":"POST","url":"https://api.example.com/v1/widgets?draft=true"}'const res = await fetch("https://api.kit.forhosting.com/dev2/curl-command-build", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"method": "POST",
"url": "https://api.example.com/v1/widgets?draft=true"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/dev2/curl-command-build",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"method": "POST",
"url": "https://api.example.com/v1/widgets?draft=true"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/dev2/curl-command-build", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"method":"POST","url":"https://api.example.com/v1/widgets?draft=true"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"method":"POST","url":"https://api.example.com/v1/widgets?draft=true"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/dev2/curl-command-build", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"method": "POST",
"url": "https://api.example.com/v1/widgets?draft=true"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "dev2.curl_command_build",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |