curl mengirim request HTTP dari terminal lalu mencetak response-nya apa adanya. Ini cara paling cepat mengetes API tanpa bikin halaman web. Bayangkan kirim paket lewat kurir: kamu menentukan jenis kirimannya (method: GET, POST, DELETE), label di bungkusnya (header, misalnya "isinya JSON"), dan isinya (body). Kurirnya pulang membawa balasan: kode status, label balasan, dan isi balasan.
🧪 Tebakan cepat: API di
http://localhost:3000/userscuma mau menerima JSON. Kamu menjalankancurl -d '{"name":"budi"}' http://localhost:3000/users. User budi berhasil dibuat? Tebak dulu, jawabannya ada di bagian "Kirim data: -d dan Content-Type".
Request paling sederhana: GET
Tanpa flag apa pun, curl mengirim GET dan mencetak body response-nya:
$ curl http://localhost:3000/users
[{"id":1,"name":"ani"}]
$ curl -i http://localhost:3000/users
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 24
[{"id":1,"name":"ani"}]
- Perintah pertama cuma menampilkan body.
-i(include) ikut menampilkan status (200 OK) dan header response di atas body. Baris kosong memisahkan header dan body.
Pilih method: -X
-X (huruf X besar) menentukan method-nya. Tanpa -X, method-nya GET.
$ curl -i -X DELETE http://localhost:3000/users
HTTP/1.1 405 Method Not Allowed
Allow: GET, POST
Content-Type: application/json
Content-Length: 31
{"error":"Method Not Allowed"}
Server menolak dengan 405 dan memberi tahu lewat header Allow method apa saja yang boleh. Status yang diawali 2 berarti berhasil, 4 berarti salah di request-mu, 5 berarti server-nya yang bermasalah.
Kirim data: -d dan Content-Type
-d (data) mengisi body dan otomatis mengubah method jadi POST, jadi -X POST gak wajib. Body-nya dikirim persis seperti yang kamu tulis. Masalahnya ada di label: tanpa -H, curl memberi label Content-Type: application/x-www-form-urlencoded, yaitu "isinya data formulir", walaupun yang kamu tulis JSON.
$ curl -i -d '{"name":"budi"}' http://localhost:3000/users
HTTP/1.1 415 Unsupported Media Type
Content-Type: application/json
Content-Length: 50
{"error":"Content-Type must be application/json"}
$ curl -i -X POST -H "Content-Type: application/json" -d '{"name":"budi"}' http://localhost:3000/users
HTTP/1.1 201 Created
Content-Type: application/json
Content-Length: 23
{"id":2,"name":"budi"}
Jadi tebakannya: gagal. Server menerima body yang benar, tapi labelnya bilang formulir, dan API yang cuma mau JSON membalas 415 Unsupported Media Type. Itu jawaban tebakannya. Perintah kedua adalah pola standar POST JSON:
-X POSTmenulis method-nya terang-terangan. Boleh dihapus, karena-dsudah membuatnya POST.-H "Content-Type: application/json"menambah header. Formatnya"Nama: nilai", dan-Hboleh diulang untuk header lain.-d '{"name":"budi"}'adalah body-nya. Bungkus JSON dengan tanda kutip satu, supaya tanda kutip dua di dalamnya gak dimakan shell.- URL boleh di depan atau di belakang. curl tahu mana yang URL: kata yang bukan flag dan bukan pasangan sebuah flag.
curl versi 7.82 ke atas juga punya --json '{"name":"budi"}', singkatan untuk POST dengan Content-Type dan Accept JSON sekaligus.
Intip semuanya: -v
-v (verbose) menampilkan request yang benar-benar dikirim dan response yang diterima. Ini alat debug API paling dasar:
$ curl -v -d '{"name":"budi"}' http://localhost:3000/users
* Trying [::1]:3000...
* Connected to localhost (::1) port 3000
> POST /users HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/8.5.0
> Accept: */*
> Content-Length: 15
> Content-Type: application/x-www-form-urlencoded
>
< HTTP/1.1 415 Unsupported Media Type
< Content-Type: application/json
< Content-Length: 50
<
{"error":"Content-Type must be application/json"}
* Connection #0 to host localhost left intact
- Baris
>adalah yang dikirim curl. Di sini kelihatan biang masalahnya: labelx-www-form-urlencodedyang gak pernah kamu tulis. - Baris
<adalah yang diterima dari server. - Baris
*adalah catatan curl sendiri soal koneksi. Isinya sedikit beda antar versi curl.
Flag lain yang sering dipakai
| Flag | Gunanya |
|---|---|
-s |
silent, sembunyikan progress bar (enak di script) |
-o hasil.json |
simpan body ke file, bukan ke layar |
-O |
simpan ke file dengan nama dari URL |
-L |
ikuti redirect (status 301, 302) sampai alamat akhirnya |
-I |
kirim HEAD, cuma minta header tanpa body |
-w "%{http_code}\n" |
cetak kode status setelah response |
-u budi:rahasia |
login Basic Auth |
-H "Authorization: Bearer $TOKEN" |
kirim token |
-k |
lewati pemeriksaan sertifikat TLS (bahaya, baca jebakannya) |
Contoh cek cepat apakah server hidup: curl -s -o /dev/null -w "%{http_code}\n" http://localhost:3000/users mencetak 200 saja.
⚠️ Jebakan yang sering ketemu
- Kirim JSON tanpa Content-Type.
-dsaja memberi label formulir, jadi API JSON membalas 415 atau membaca body-nya kosong. Tambahkan-H "Content-Type: application/json". - JSON dibungkus tanda kutip dua.
-d "{"name":"budi"}"membuat shell membuang tanda kutip di dalamnya, dan server menerima{name:budi}. Pakai tanda kutip satu di luar. - Mengira
-X POSTsudah mengirim data.-Xcuma mengganti nama method. Body baru ada kalau ada-d. -kdi production atau CI.-k(--insecure) mematikan pemeriksaan sertifikat TLS, jadi penyerang di tengah jalan bisa menyamar jadi server-mu tanpa ketahuan (man-in-the-middle). Pakai hanya untuk server lokal dengan sertifikat buatan sendiri.
TL;DR: curl URL mengirim GET dan mencetak body. -X menentukan method, -H "Nama: nilai" menambah header, -d mengisi body dan otomatis membuat method jadi POST (kalau -X gak ditulis). Body dikirim apa adanya, tapi labelnya formulir, jadi untuk JSON tambahkan -H "Content-Type: application/json" dan bungkus JSON dengan tanda kutip satu. -i menampilkan status dan header response, -v menampilkan semua yang dikirim (>) dan diterima (<). URL adalah kata yang bukan flag dan bukan pasangan flag. Jangan pakai -k di production.