🔀 cURL to Java

Paste a curl command, get working Java for five HTTP clients. No request is ever sent.

JDK 11+, no dependency at all
CURL COMMAND
JAVA
🔀

Paste a curl command on the left

Five clients · nothing is ever sent · 100% private

From a curl command to Java

Every browser's network tab has a "Copy as cURL", every API's docs open with a curl example, and every Java service then needs the same request expressed in whichever HTTP client that codebase uses. That translation is mechanical, and it goes wrong in the same three places every time.

The quoting

A real curl command is mostly a quoted JSON body full of spaces, colons, braces and escaped quotes. Converters that split on whitespace mangle it while looking like they worked. This one tokenises the way a shell does — single quotes literal, double quotes with backslash escapes — and joins Unix \, Windows ^ and PowerShell backtick line continuations.

curl's defaults

-d with no -X means POST, and -d with no Content-Type means application/x-www-form-urlencoded — not JSON. That second one is behind a large share of the 415s people spend an afternoon on. -G moves the data into the query string instead of the body. All three are reproduced, and the converter says when it applied one.

What cannot be translated honestly

-k is one flag in curl and a JVM-wide hole in Java: it means installing a TrustManager that accepts every certificate. The converter refuses to generate it and explains why, because the alternative is a copy-pasteable snippet that silently disables TLS verification in a service.

Frequently asked

Does this send the request?

No, and it never will. Firing a request from this page would mean proxying it through our server, which is an open relay pointed at whatever host a stranger types — including addresses inside our own network. This tool is pure text: a curl command in, Java out, entirely in your browser.

Why did my -d body come out as form-urlencoded?

Because that is curl's default. -d without an explicit Content-Type sends application/x-www-form-urlencoded, not JSON — which is why so many hand-translated requests come back 415. The converter reproduces curl's behaviour and tells you when it did, so you can change it deliberately.

Why won't it translate -k / --insecure?

Because there is no small honest version. Disabling certificate verification in Java means installing a trust-all TrustManager, which switches off certificate checking far more broadly than the one request you were debugging. Generating that quietly would be the most damaging thing this tool could do, so it warns instead.

Which client should I pick?

java.net.http needs no dependency at all and is the right default on JDK 11+. RestTemplate is still what most existing Spring codebases use, WebClient is its supported successor, OkHttp is the standard on Android, and Feign is the declarative option if you are already on Spring Cloud.

It got my quoted JSON body wrong in another tool — why?

Almost every curl converter splits the command on whitespace, which mangles any quoted body containing spaces, colons or escaped quotes. This one tokenises the way a shell does: single quotes are literal, double quotes allow backslash escapes, and Unix, Windows and PowerShell line continuations are all joined.

Translating a curl command into Java HTTP client code

Every browser network tab has a "Copy as cURL", every API's documentation opens with a curl example, and every Java service then needs that same request expressed in whichever HTTP client the codebase already uses. The translation is mechanical, which is exactly why it gets done by hand and why it goes wrong in the same three places every time: the quoting, curl's implicit defaults, and the one flag that has no honest Java equivalent.

Braxik's cURL to Java converter parses a pasted command and emits code for five clients: java.net.http (the JDK 11+ client, and the default selection on the page because it needs no dependency at all), Spring's RestTemplate, Spring WebFlux's WebClient, Square's OkHttp, and a Spring Cloud OpenFeign interface. Pick a target and the same parsed request is re-emitted; you are not re-pasting anything.

No request is ever sent, and that is a design decision rather than a missing feature. Firing the request from this page would mean proxying it through a server, which is an open relay pointed at whatever host a stranger types — including addresses inside the operator's own network. The tool is pure text transformation: a command in, Java out, entirely inside your browser tab.

The parsing is the part that separates this from a regular expression over the command string. A real pasted curl is mostly a quoted JSON body full of spaces, colons, braces and escaped quotes, and a converter that splits on whitespace mangles all of it while appearing to have worked. This one tokenises the way a shell does, then reproduces curl's own defaults and tells you each time it applied one.

How it works

Tokenising comes first. Single quotes are taken literally, double quotes allow backslash escapes for the four characters a shell honours inside them, and line continuations are joined for all three shells people paste from: a trailing backslash from a Unix terminal, a caret from Windows cmd, and a backtick from PowerShell. Combined short flag groups are expanded before parsing, so a pasted `-sX POST` is read as `-s` followed by `-X POST` rather than as one unknown flag.

The tokens are then folded into a request record. A header is split on its FIRST colon only, so a `Referer: https://a.test/x` value keeps its own colons. `-u user:pass` is deliberately kept out of the header list, because each target has its own helper — `headers.setBasicAuth`, `Credentials.basic`, WebClient's `headers(h -> h.setBasicAuth(...))` — and hand-rolling Base64 four different ways is how one of them ends up wrong. Repeated `-d` values are joined with `&` the way curl joins them, `-G` moves that joined string into the query string instead of the body, and `-I` becomes HEAD.

Curl's defaults are then applied explicitly. A body with no `-X` makes the method POST. A body with no Content-Type header gets `application/x-www-form-urlencoded`, because that is what curl sends — and a warning saying so, since assuming JSON here is behind a large share of the 415s people lose an afternoon to. `--json` adds both Content-Type and Accept as `application/json`. A URL with no scheme gets `https://` and a note, because `java.net.URI` refuses to parse a schemeless string and the alternative is code that throws on its first line.

Emission is per-target and per-request. String literals are escaped so the JSON's own quotes do not close the literal early, and a body containing newlines is emitted as a Java text block with the closing `"""` on its own line, since the closing delimiter is what sets the indentation stripped from every line. The import block is computed from what the request actually needs — `okhttp3.RequestBody` appears only when there is a body — and can be switched off entirely from the output pane options.

Common uses

  • Turn a "Copy as cURL" from Chrome or Firefox DevTools into a reproducible integration test against a third-party API.
  • Convert the curl example in a payment gateway's or a partner's documentation into the RestTemplate call your existing Spring service already uses everywhere else.
  • Get the same request in WebClient form while migrating a blocking Spring MVC service towards WebFlux, without re-deriving the headers by hand.
  • Scaffold a Feign interface from a curl command: the host becomes the client's `url`, the path and query become the mapping annotation, and each header becomes a `@RequestHeader` parameter.
  • Work out why a hand-written Java call returns 415 when the curl succeeds, by seeing which Content-Type curl was actually sending.
  • Reproduce a multipart upload — `-F name=value` plus `-F file=@/path` — as MultipartBody, MultipartBodyBuilder or LinkedMultiValueMap without looking up the API for each.
  • Paste an OkHttp-bound request for an Android client from the same curl the backend team shared in a ticket.
  • Attach generated Java to a bug report so a reviewer can run the exact request from a JUnit test rather than from a shell.

Before you rely on the result

  • `-k` / `--insecure` is never translated. In Java it means installing a trust-all TrustManager, which switches off certificate verification far beyond the one request you were debugging — the converter warns instead of emitting it, and the generated code contains no TrustManager at all.
  • A `-d` body that is really JSON still needs its Content-Type changed by hand. The converter reproduces curl's form-urlencoded default faithfully, which means it reproduces the mistake faithfully too.
  • Timeouts (`-m`, `--connect-timeout`) and redirect following (`-L`) are only expressed on the java.net.http builder. On the other four targets they are parsed but have no emitted equivalent, so configure them on your own client bean.
  • A `-F field=@/tmp/file.png` upload generates code pointing at that literal path. The warning names the path; change it to something the JVM running your code can actually read.
  • Basic auth credentials from `-u` are written into the generated source as plain string literals. Move them to configuration or a secrets store before the snippet reaches a repository.
  • Flags the converter does not translate are listed as warnings rather than ignored, so read the warning panel — `--retry 3` disappearing silently would be a behavioural difference nobody would look for later.
  • The generated code is a working request, not production code: there is no error handling for non-2xx responses, no connection pooling, no retry policy, and the response is deserialised as `String` rather than into a typed DTO.
  • A shared link carries the whole command, including any Authorization header in it. The Share button scans for secrets and turns itself into a confirmation when it finds one — read that prompt rather than clicking through it.