Skip to main content

yet another library to convert request object to curl command

Project description

curlify3

Convert request objects from popular Python HTTP libraries into ready-to-run curl commands.

PyPI Downloads Python Tests

curlify3 takes a request object from any supported client or server framework and renders it as an equivalent curl command — useful for logging, debugging, sharing reproductions, and copy-pasting from your IDE into a terminal.

Features

  • Single dispatch entrypoint — to_curl() (sync) and to_curl_async() (async)
  • Works with client-side requests (requests, httpx, httpx2) and server-side incoming requests (aiohttp.web, starlette / fastapi)
  • Faithful rendering of headers, query parameters, cookies (-b), and bodies
  • Body payloads: text, JSON, form-encoded, multipart, binary
  • Zero runtime dependencies

Installation

pip install curlify3

Requires Python 3.10+.

Comparison with curlify and curlify2

curlify curlify2 curlify3
requests [x] [x] [x]
httpx [ ] [x] [x]
httpx2 (HTTP/2) [ ] [ ] [x]
aiohttp (server-side) [ ] [ ] [x]
starlette / fastapi (server-side) [ ] [ ] [x]
Async API [ ] [ ] [x]
Python 3.7+ 3.7–3.11 3.10+

curlify is the original and covers only requests. curlify2 added httpx but is sync-only, client-side-only, and has not seen a release since 2023. curlify3 extends the same idea with HTTP/2 (httpx2), an async entrypoint, and server-side adapters for aiohttp and starlette / fastapi so you can dump incoming requests as curl from inside a handler.

Quick start

import requests
from curlify3 import to_curl

response = requests.get("https://httpbin.org/get")
print(to_curl(response.request))
# curl -H 'user-agent: python-requests/2.32.3' -H 'accept-encoding: gzip, deflate' \
#      -H 'accept: */*' -H 'connection: keep-alive' https://httpbin.org/get

Usage

requests

import requests
from curlify3 import to_curl

req = requests.Request(
    "POST",
    "https://httpbin.org/post",
    json={"hello": "world"},
).prepare()

print(to_curl(req))

httpx (sync)

import httpx
from curlify3 import to_curl

req = httpx.Request("POST", "https://httpbin.org/post", json={"hello": "world"})
print(to_curl(req))

httpx (async)

import asyncio
import httpx
from curlify3 import to_curl_async

async def main():
    req = httpx.Request("POST", "https://httpbin.org/post", json={"a": 1})
    print(await to_curl_async(req))

asyncio.run(main())

httpx2 — HTTP/2

The generated command includes --http2.

import httpx2
from curlify3 import to_curl

req = httpx2.Request("GET", "https://httpbin.org/get")
print(to_curl(req))
# curl --http2 -H 'host: httpbin.org' https://httpbin.org/get

to_curl_async() works with httpx2.Request too.

aiohttp — server-side

Render an incoming request inside a handler. The async variant is required because the body is read from the stream.

from aiohttp import web
from curlify3 import to_curl_async

async def handler(request: web.Request) -> web.Response:
    curl = await to_curl_async(request)
    print(curl)
    return web.json_response({"ok": True})

starlette / fastapi — server-side

from fastapi import FastAPI, Request
from curlify3 import to_curl_async

app = FastAPI()

@app.post("/echo")
async def echo(request: Request):
    curl = await to_curl_async(request)
    return {"curl": curl}

API

to_curl(request) -> str

Render a request object as a curl command. Use for synchronous request types (requests.PreparedRequest, httpx.Request, httpx2.Request).

to_curl_async(request) -> str

Async variant. Use for server-side request objects whose body must be await-ed (aiohttp.web.Request, starlette.requests.Request) or when you prefer the async pathway for httpx / httpx2.

Both functions raise ValueError("unknown request object") if the request type is not recognized.

Supported request objects

Library Type to_curl to_curl_async Notes
requests PreparedRequest [x] [ ] Pass Request(...).prepare()
httpx httpx.Request [x] [x]
httpx2 httpx2.Request [x] [x] Adds --http2
aiohttp aiohttp.web.Request [ ] [x] Server-side
starlette / fastapi starlette.requests.Request [ ] [x] Server-side

Payload handling

Payload Rendered as
Plain text -d 'text'
JSON -d '{"k":"v"}' with content-type: application/json
Form-encoded -d 'k=v&k2=v2' with content-type: application/x-www-form-urlencoded
Multipart / files -F 'field=@file' -F 'other=value'
Binary -d with raw bytes (falls back when not UTF-8)
Cookies -b 'k=v' (lifted out of Cookie header)
Headers -H 'name: value' (lowercased)

Content-Length is dropped. If a body is present without Content-Type, content-type: plain/text is added so curl does not guess.

Development

The project uses uv and just.

uv sync --group dev
just tests   # uv run pytest -vv
just fmt     # isort + black

CI runs the test suite on Python 3.10–3.14.

Changelog

See CHANGELOG.md.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

curlify3-0.7.tar.gz (6.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

curlify3-0.7-py3-none-any.whl (7.4 kB view details)

Uploaded Python 3

File details

Details for the file curlify3-0.7.tar.gz.

File metadata

  • Download URL: curlify3-0.7.tar.gz
  • Upload date:
  • Size: 6.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for curlify3-0.7.tar.gz
Algorithm Hash digest
SHA256 7c8367499d7cd9134b8f987f25acd1c2126dc0215253ab12fc71c40a242d700d
MD5 40557fcad9463467e031615c5494cd71
BLAKE2b-256 0b77b2a9d6beb691c21caa25fa18cd3fca61481cc67fb20e82f78c1b92a6bd18

See more details on using hashes here.

File details

Details for the file curlify3-0.7-py3-none-any.whl.

File metadata

  • Download URL: curlify3-0.7-py3-none-any.whl
  • Upload date:
  • Size: 7.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for curlify3-0.7-py3-none-any.whl
Algorithm Hash digest
SHA256 002011e2d042392095fd6e809e4dfe3e03325643a3b952597c24045da3017ccd
MD5 f6b57bb5b6addffe73ab83702928d70f
BLAKE2b-256 f06bdf47d5eb234031f0786060f96239530e3c7b43862cf2de86b4efec526e89

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page