Send multipart form-data with cURL in Swift

Paste a curl command that sends multipart form-data and get idiomatic Swift code. We pick the right serialization for URLSession and set the correct Content-Type.

Quick answer

To convert a cURL command to Swift, paste it into the Toolpaper workbench below. It parses the command in your browser and emits idiomatic Swift code — headers, query string, request body, authentication (Bearer, Basic, API key), and cookies are all wired up automatically. No data is uploaded; conversion is fully client-side.

Prefer a different target? See the full cURL to Swift reference, or jump to the same guide in JavaScript, Node.js, or Python.

InputcURL command
MethodPOST·Headers0·Body—·Form2 fields· Chars 100
OutputApple · URLSession(async/await)
import Foundation

let session = URLSession.shared
var request = URLRequest(url: URL(string: "https://api.example.com/upload")!)
request.httpMethod = "POST"
// Multipart body — Swift has no built-in helper. Consider Alamofire for real uploads.
let boundary = "----ToolpaperBoundary\(UUID().uuidString)"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
var body = Data()
body.append("--\(boundary)\r\n".data(using: .utf8)!)
body.append("Content-Disposition: form-data; name=\"file\"; filename=\"/path/to/photo.png\"\r\n".data(using: .utf8)!)
body.append("Content-Type: application/octet-stream\r\n\r\n".data(using: .utf8)!)
body.append(try Data(contentsOf: URL(fileURLWithPath: "/path/to/photo.png")))
body.append("\r\n".data(using: .utf8)!)
body.append("--\(boundary)\r\n".data(using: .utf8)!)
body.append("Content-Disposition: form-data; name=\"caption\"\r\n\r\nHello".data(using: .utf8)!)
body.append("\r\n".data(using: .utf8)!)
body.append("--\(boundary)--\r\n".data(using: .utf8)!)
request.httpBody = body

let (data, response) = try await session.data(for: request)
print(String(data: data, encoding: .utf8) ?? "")
// Note: to disable redirects, implement URLSessionTaskDelegate.urlSession(_:task:willPerformHTTPRedirection:...) and return nil.
Inspect

Example

A representative curl command for this scenario. Paste your own above to convert an exact match.

curl input
curl -X POST https://api.example.com/upload \
  -F "file=@/path/to/photo.png" \
  -F "caption=Hello"

Implementation notes

  • Content-Type is detected from -H headers first, then inferred from the body shape when the header is missing.
  • Each -F flag becomes a distinct part; file@ paths are surfaced as URLSession file handles so the multipart boundary stays valid.
  • Charset directives on Content-Type (e.g. application/json; charset=utf-8) survive the round trip.

Common mistakes

  • Setting Content-Type manually and then also using URLSession's helper — you end up with duplicate headers or the wrong one wins.
  • Forgetting @ in -F "file=@upload.png" — without it curl sends the literal string, not the file. The generator flags this.
  • Trusting the browser DevTools "Copy as cURL" to preserve charset — it often drops it. Clean panel restores common defaults.

Common questions

How is multipart form-data encoded in the generated Swift?
-F flags translate to multipart form-data with proper boundary handling — files={...} in Python, MultipartFormDataContent in C#, MultipartBody.Part in Java/Kotlin.
Does it preserve Content-Type?
Yes. The Content-Type header is honored and matched against the body so serialization stays consistent.
Is anything uploaded?
No. Parsing and generation happen entirely in your browser.

More payload types in Swift

Swift hub →

The same guide in other languages

All guides →

Full Swift reference on the cURL to Swift hub, or open the main converter for all 18 targets.