Geonode logo
Geonode Team

Geonode Team

Diperbarui: 7 Oktober 2026

Diterbitkan: 2 September 2026

Cara Melakukan Permintaan HEAD dengan curl

`curl -I` mengirimkan permintaan HEAD. `curl -X HEAD` sepertinya seharusnya melakukan hal yang sama, namun justru melakukan sesuatu yang sedikit bermasalah, yang bisa membuat Anda menghabiskan dua puluh menit karena terminal macet. Manual curl menjelaskan hal ini secara langsung, dan alasannya layak dipahami karena berlaku untuk setiap metode yang mungkin Anda atur secara manual. Panduan ini membahas sintaks yang benar, aturan spesifikasi mengenai apa yang boleh diabaikan oleh server, serta kasus-kasus di mana permintaan HEAD memberikan informasi yang tidak diberikan oleh permintaan GET.

Alasan kami peduli: kami adalah Geonode dan kami menjual layanan proxy, sehingga orang-orang terus-menerus menggunakan permintaan HEAD melalui layanan kami untuk memeriksa tautan, ukuran, dan ketersediaan dengan biaya murah. Peringatan yang jujur adalah bahwa HEAD adalah permintaan yang berbeda, bukan GET yang ringan, dan memperlakukannya sebagai GET akan menghasilkan kesimpulan yang salah. Sebuah URL yang mengembalikan kode status 200 saat menerima permintaan HEAD mungkin mengembalikan kode status 403 saat menerima permintaan GET. Sumber daya yang tidak menampilkan "Content-Length" saat diakses dengan HEAD mungkin menampilkannya saat diakses dengan GET. Selain itu, lapisan anti-bot mungkin menganggap permintaan HEAD yang tidak biasa sebagai sinyal tersendiri. HEAD sangat baik untuk tujuan aslinya; namun, HEAD bukanlah indikator yang tepat untuk "apa yang akan terjadi jika saya benar-benar mengambil data ini".

Cara yang Benar

curl -I https://example.com

Manual curl mendokumentasikan perintah -I, --head

sebagai berikut: "(HTTP FTP FILE) Mengambil header saja. Server HTTP memiliki perintah HEAD yang digunakan untuk mengambil hanya header dari sebuah dokumen. Saat digunakan pada URL FTP atau FILE, curl hanya menampilkan ukuran file dan waktu modifikasi terakhir."

Hasil:

HTTP/2 200
content-type: text/html; charset=UTF-8
content-length: 1256
last-modified: Thu, 17 Oct 2019 07:18:26 GMT
cache-control: max-age=604800

Itulah jawaban lengkap untuk pertanyaan di judul. Bagian berikut ini adalah bagian yang menghemat waktu.

Mengapa Perintah -X HEAD Salah

Panduan curl membahas hal ini secara langsung di bagian “-X, --request”:

Opsi ini hanya mengubah kata yang sebenarnya digunakan dalam permintaan HTTP; opsi ini tidak mengubah cara kerja curl. Misalnya, jika Anda ingin membuat permintaan HEAD yang benar, menggunakan -X HEAD saja tidak cukup. Anda perlu menggunakan opsi --head.

Mekanismenya: -X hanya menukar string metode dan tidak mengubah hal lain. curl tetap berperilaku seolah-olah sedang melakukan permintaan GET, yang berarti curl tetap mengharapkan isi respons. Server, yang mengimplementasikan HEAD dengan benar, mengirimkan header dan tidak ada isi. curl menunggu konten yang tidak akan pernah tiba, dan perintah tersebut tampak macet hingga batas waktu habis atau koneksi ditutup.

Manual juga memperingatkan tentang perilaku "-X" kedua yang sering menjebak pengguna saat terjadi pengalihan: "Jika opsi --location digunakan, string metode yang Anda tetapkan dengan --request akan diterapkan pada semua permintaan". Jadi, -X POST -L akan mengirim ulang permintaan POST ke setiap langkah dalam rantai pengalihan, yang jarang menjadi niat siapa pun.

Prinsip umumnya, sebagaimana dinyatakan dalam manual itu sendiri: "Biasanya Anda tidak memerlukan opsi ini. Segala jenis permintaan GET, HEAD, POST, dan PUT lebih baik dipanggil dengan menggunakan opsi baris perintah khusus." Gunakan -I untuk HEAD, -d untuk POST, -T untuk PUT, dan sisihkan -X untuk metode yang benar-benar tidak umum seperti PROPFIND.

Apa Sebenarnya HEAD Itu

RFC 9110 §9.3.2 mendefinisikannya dalam satu kalimat:

Metode HEAD identik dengan GET, kecuali bahwa server TIDAK BOLEH mengirimkan konten dalam responsnya.

Dan menyatakan tujuannya: "HEAD digunakan untuk memperoleh metadata tentang representasi yang dipilih tanpa mentransfer data representasinya, seringkali untuk tujuan menguji tautan hiperteks atau menemukan modifikasi terbaru."

Itu merupakan persyaratan yang ketat bagi server — MUST NOT mengirimkan konten — dan itulah sebabnya curl macet ketika diperintahkan untuk mengharapkan adanya konten.

Aturan header sengaja dibuat lebih longgar, dan inilah bagian yang sering disalahpahami orang:

Server SEBAIKNYA mengirimkan bidang header yang sama dalam respons terhadap permintaan HEAD seperti yang akan dikirimkan jika metode permintaannya adalah GET. Namun, server DAPAT mengabaikan bidang header yang nilainya ditentukan hanya saat menghasilkan konten.

RFC memberikan contoh konkret: server yang menyimpan respons dinamis dalam buffer mungkin menghasilkan Content-Length dan Vary pada permintaan GET yang "tidak dihasilkan dalam respons HEAD". RFC menyebut hal ini sebagai "ketidakkonsistenan kecil" dan menganggapnya "lebih disukai daripada menghasilkan dan membuang konten untuk permintaan HEAD, karena HEAD biasanya diminta demi efisiensi."

Jadi, tidak adanya Content-Length pada permintaan HEAD tidak selalu merupakan bug dan tidak selalu bermakna. Hal ini mungkin hanya menunjukkan bahwa server menolak untuk menghitung sesuatu yang hanya akan diketahui dengan merender halaman tersebut.

Ada juga aturan mengenai badan permintaan yang perlu diketahui jika Anda sedang mengembangkan alat. Konten dalam permintaan HEAD "tidak memiliki semantik yang didefinisikan secara umum, tidak dapat mengubah makna atau tujuan permintaan, dan mungkin menyebabkan beberapa implementasi menolak permintaan serta menutup koneksi karena potensinya sebagai serangan request smuggling". RFC menyatakan bahwa klien "SEBAIKNYA TIDAK menghasilkan konten dalam permintaan HEAD" kecuali ada kesepakatan khusus sebelumnya. Jangan mengirimkan badan permintaan (body) bersama permintaan HEAD.

Kegunaan HEAD

Contoh-contoh yang benar-benar berguna, yang semuanya menukar transfer penuh dengan beberapa ratus byte.

Memeriksa apakah sebuah URL masih aktif:

curl -sI -o /dev/null -w '%{response_code}\n' https://example.com

Mencari tahu ukuran file sebelum mengunduh:

curl -sI https://example.com/large.iso | grep -i content-length

Melacak dan melaporkan rantai pengalihan:

curl -sIL -o /dev/null -w '%{num_redirects} hops -> %{url_effective}\n' https://example.com

Memeriksa apakah server mendukung permintaan rentang, yang menentukan apakah unduhan yang terputus dapat dilanjutkan:

curl -sI https://example.com/file.zip | grep -i accept-ranges

Memeriksa keaktualan tanpa mengunduh:

curl -sI https://example.com/data.json | grep -iE 'last-modified|etag'

Pemeriksaan tautan massal, yang merupakan penggunaan klasik dan di sinilah penghematan bandwidth semakin terasa:

while read -r url; do
  code=$(curl -sIL -o /dev/null -w '%{response_code}' --max-time 10 "$url")
  echo "$code $url"
done < urls.txt

Dengan bandwidth yang dibatasi, penghematannya nyata: pemeriksaan tautan yang seharusnya mentransfer 500 KB per URL hanya mentransfer beberapa ratus byte saja. Untuk sepuluh ribu URL, itu berarti perbedaan antara lima gigabyte dan beberapa megabyte.

Ketika HEAD Menyesatkan Anda

Berbagai skenario kegagalan, yang menjadi alasan peringatan di bagian atas.

Server menolak permintaan HEAD sepenuhnya. 405 Method Not Allowed pada URL di mana permintaan GET berfungsi dengan sempurna. Hal ini jarang terjadi pada konten statis, namun tidak jarang pada API dan titik akhir aplikasi.

Server menangani HEAD secara berbeda. Kode status yang berbeda, header yang berbeda, terkadang jalur kode yang sama sekali berbeda dalam aplikasi. RFC mengizinkan penghilangan header yang berasal dari konten, dan implementasinya bervariasi sejauh mana hal itu diterapkan.

Cache dan CDN mungkin mengindeks HEAD secara terpisah. Header cache pada HEAD dapat mencerminkan entri cache yang berbeda dari yang akan diakses oleh GET, sehingga HEAD bukanlah cara yang andal untuk memeriksa perilaku caching.

Sistem anti-bot merespons secara berbeda. Permintaan HEAD dari klien yang tidak dikenal itu sendiri merupakan sinyal, dan respons yang Anda terima mungkin tidak sama dengan yang akan diterima oleh permintaan GET dari browser.

Informasi ``Content-Length mungkin tidak ada atau salah. Hal ini diizinkan oleh spesifikasi, umum terjadi pada konten dinamis, dan bukan dasar yang baik untuk memperkirakan ukuran unduhan pada konten yang dihasilkan.

Rantai pengalihan mungkin berbeda. Beberapa server mengalihkan permintaan GET dan HEAD ke lokasi yang berbeda, terutama jika melibatkan negosiasi konten.

Jika Anda perlu mengetahui apa yang akan dilakukan oleh permintaan sebenarnya, lakukan permintaan yang sebenarnya dan abaikan isinya:

curl -sS -o /dev/null -D - https://example.com

Permintaan GET yang sesungguhnya, header ditampilkan di stdout, isi diabaikan. Anda membayar biaya bandwidth, dan Anda mendapatkan jawaban yang akurat. Pilihlah dengan cermat di antara keduanya: -I jika Anda menginginkan yang murah, -o /dev/null -D - jika Anda menginginkan yang akurat.

Terdapat opsi tengah untuk sumber daya berukuran besar — minta satu byte alih-alih seluruhnya:

curl -sS -r 0-0 -o /dev/null -D - https://example.com/large.iso

-r, --range mengambil "rentang byte (yaitu dokumen sebagian)", sehingga 0-0 hanya mengambil byte pertama. Ini adalah permintaan GET yang sesungguhnya dengan perilaku GET yang sesungguhnya, hampir tanpa biaya bandwidth. Peringatan dari manual: "Banyak server HTTP/1.1 tidak mengaktifkan fitur ini", jadi periksa terlebih dahulu Accept-Ranges: bytes dan harapkan respons lengkap jika fitur tersebut tidak tersedia.

Pola yang Layak Ditiru dalam Skrip

Perintah-perintah di atas menjadi jauh lebih berguna jika dilengkapi dengan sedikit struktur.

Pemeriksa tautan yang memberikan laporan yang akurat. Versi sederhana menganggap setiap respons selain 200 sebagai tautan rusak, yang menyebabkan peringatan palsu pada pengalihan (redirect) dan pada server yang menolak permintaan HEAD. Versi ini membedakannya:

check() {
  local url="$1" code
  code=$(curl -sIL -o /dev/null --max-time 10 -w '%{response_code}' "$url")
  case "$code" in
    200) echo "OK       $url" ;;
    405) code=$(curl -sSL -o /dev/null --max-time 10 -w '%{response_code}' "$url")
         echo "GET:$code $url" ;;
    000) echo "TIMEOUT  $url" ;;
    *)   echo "$code     $url" ;;
  esac
}

Cabang 405 sangat penting: server yang menolak HEAD bukanlah tautan rusak, dan mencoba kembali dengan metode GET adalah satu-satunya cara untuk mengetahuinya. 000 adalah cara curl melaporkan bahwa tidak ada respons HTTP yang diterima sama sekali, yang membedakan kegagalan jaringan dari kesalahan server.

Paralelisme, dengan hati-hati. Pemeriksaan tautan sangat mudah dilakukan secara paralel, dan godaan untuk menjalankannya secara luas sangat besar. Hindari hal ini:

xargs -P 8 -I{} sh -c 'check "$1"' _ {} < urls.txt

Delapan adalah nilai default yang wajar. Batas atas di sini adalah etika dalam membebani server orang lain, bukan kapasitas server Anda sendiri; dan pemeriksa tautan yang memicu insiden pembatasan laju (rate-limiting) telah menimbulkan biaya lebih besar daripada yang dihemat.

Selalu tetapkan batas waktu. Permintaan HEAD terhadap host yang tidak merespons akan macet selama waktu yang sama dengan permintaan GET. --max-time 10 dengan --connect-timeout 5 membatasi waktu tersebut, dan dalam loop yang mencakup ribuan URL, batasan itulah yang memastikan tugas selesai.

Catat URL yang sebenarnya, bukan hanya statusnya. %{url_effective} setelah -L memberi tahu Anda ke mana tautan tersebut benar-benar mengarah, yang mengubah "tautan ini berfungsi" menjadi "tautan ini berfungsi dan sekarang mengarah ke tempat lain" — biasanya temuan yang lebih menarik.

Simpan hasil Anda dalam cache. Memeriksa ulang setiap URL pada setiap eksekusi hanya akan membuang-buang bandwidth dan kesabaran. Simpan status serta ETag atau Last-Modified, dan gunakan permintaan bersyarat pada putaran berikutnya sehingga sumber daya yang tidak berubah hanya memerlukan 304 alih-alih pemeriksaan penuh.

HEAD Melalui Proxy

Ada tiga hal yang berubah, semuanya patut diketahui.

curl -I -x http://user:pass@proxy.example.com:9000 https://example.com

Perintah CONNECT dijalankan terlebih dahulu untuk HTTPS. curl membuat terowongan sebelum perintah HEAD, dan dalam output terperinci, respons proxy terhadap perintah tersebut muncul sebelum respons target. Opsi --suppress-connect-headers menyembunyikannya; opsi %{http_connect} melaporkan status proxy secara terpisah dari status target.

Penghematan bandwidth adalah intinya. Melalui lalu lintas yang dibatasi kuota, permintaan HEAD hanya menghabiskan beberapa ratus byte dibandingkan dengan ukuran halaman penuh. Untuk validasi tautan, pemantauan ketersediaan, dan pemeriksaan ukuran dalam skala besar, inilah perbedaan antara pekerjaan yang terjangkau dan yang mahal. Ini adalah salah satu dari sedikit optimasi besar yang benar-benar tersedia pada sistem penetapan harga per gigabyte.

Namun, blokir dan tantangan berperilaku berbeda. Lapisan anti-bot yang menampilkan halaman tantangan untuk permintaan GET mungkin hanya menolak permintaan HEAD, atau sebaliknya. Jika Anda menggunakan HEAD untuk memeriksa apakah suatu target dapat diakses, verifikasilah kesimpulannya dengan melakukan permintaan GET yang sebenarnya pada sampel sebelum mempercayainya untuk seluruh daftar. Inilah pola kegagalan diam-diam yang kami bahas dalam mengapa pengujian proxy penting: permintaan berhasil, jawabannya salah, dan tidak ada yang memberi tahu Anda.

Satu detail curl yang perlu diketahui: -G, --get dapat digabungkan dengan --head. Manual tersebut menyebutkan bahwa ketika -G digunakan bersama --head, "data POST justru ditambahkan ke URL pada permintaan HEAD" — hal ini berguna ketika Anda memerlukan parameter kueri yang dibangun dari pasangan kunci-nilai pada permintaan HEAD.

Membaca Respons dengan Benar

Memanfaatkan hasil respons secara maksimal.

Perhatikan statusnya terlebih dahulu. 200 ada. 301 /302 telah dipindahkan — tambahkan -L untuk mengaksesnya. 403 ditolak. 404 tidak ada lagi. 405 berarti server tidak menerima permintaan HEAD, jadi coba lagi dengan metode GET. 429 berarti kecepatan koneksi lambat.

**Content-Length ** jika ada, ingat bahwa spesifikasi mengizinkan untuk mengabaikannya.

**Accept-Ranges: bytes ** berarti unduhan yang dapat dilanjutkan dan permintaan rentang tersedia.

**Last-Modified dan ETag ** mengaktifkan permintaan bersyarat. -z mengirimkan If-Modified-Since — manual menjelaskannya sebagai permintaan "berkas yang telah dimodifikasi setelah waktu dan tanggal yang ditentukan" — dan --etag-compare menangani sisi ETag . 304 Not Modified hampir tidak memerlukan biaya dan merupakan cara yang tepat untuk melakukan polling terhadap suatu sumber daya secara berulang.

**Content-Type ** memberi tahu Anda apa yang seharusnya Anda terima. text/html di mana Anda mengharapkan JSON biasanya berarti adanya kesalahan atau halaman login.

Untuk penggunaan oleh mesin, lewati proses parsing teks sepenuhnya:

curl -sI -o /dev/null -w '%{header_json}' https://example.com | jq

%{header_json} menampilkan semua header respons sebagai JSON dengan nama huruf kecil dan nilai array, yang menangani header berulang dengan benar dan menghilangkan kebutuhan akan parser. Kami telah membahasnya beserta opsi pemeriksaan lainnya dalam menampilkan header respons dengan curl.

Pertanyaan Lainnya

Bagaimana cara mengirim permintaan HEAD dengan curl?

curl -I https://example.com. Bentuk lengkapnya adalah --head. Jangan gunakan -X HEAD — manualnya secara eksplisit menyatakan bahwa hal itu "tidak cukup" untuk permintaan HEAD yang benar, karena perintah tersebut hanya mengubah string metode sementara curl tetap mengharapkan isi respons.

Mengapa curl -X HEAD macet?

Karena -X hanya mengubah kata dalam baris permintaan, bukan perilaku curl. curl tetap menunggu badan respons, sementara server dengan benar tidak mengirimkannya, karena RFC 9110 mensyaratkan bahwa server "TIDAK BOLEH mengirim konten" dalam respons HEAD. Gunakan -I sebagai gantinya.

Apa perbedaan antara HEAD dan GET?

HEAD identik dengan GET kecuali bahwa server tidak boleh mengirimkan isi respons. Perintah ini ada untuk memperoleh metadata tanpa mentransfer konten, biasanya untuk memeriksa tautan atau menguji keaktualan. Server harus mengirimkan header yang sama seperti yang mereka kirimkan untuk GET, tetapi boleh mengabaikan header yang hanya dihitung saat menghasilkan konten.

Apakah HEAD selalu mengembalikan header yang sama seperti GET?

Tidak. Spesifikasi menyatakan bahwa server SEBAIKNYA mengirimkan header yang sama, tetapi BOLEH mengabaikan header "yang nilainya ditentukan hanya saat menghasilkan konten" — spesifikasi tersebut menyebutkan Content-Length dan Vary sebagai contoh. Spesifikasi tersebut menyatakan bahwa ketidakkonsistenan kecil ini lebih disukai daripada menghasilkan dan membuang isi respons.

Bagaimana cara mengetahui ukuran file tanpa mengunduhnya?

Gunakan perintah curl -sI URL | grep -i content-length. Perlu diperhatikan bahwa header tersebut mungkin tidak ada pada konten yang dihasilkan secara dinamis, yang diperbolehkan oleh spesifikasi. Untuk jawaban yang lebih andal dengan biaya hampir nol, kirimkan permintaan satu byte menggunakan -r 0-0 dan baca header Content-Range.

Mengapa sebuah URL berfungsi di browser tetapi mengembalikan kode status 405 saat menggunakan curl -I?

Karena server tidak menerima permintaan HEAD pada endpoint tersebut. 405 Method Not Allowed adalah respons yang valid untuk permintaan HEAD dari server yang menangani permintaan GET dengan baik. Coba ulang dengan permintaan GET dan buang isi (body): curl -sS -o /dev/null -D - URL.

Bisakah saya mengirim permintaan HEAD dengan isi?

Sebaiknya tidak. RFC 9110 menyatakan bahwa konten dalam permintaan HEAD "tidak memiliki semantik yang didefinisikan secara umum", tidak dapat mengubah makna permintaan, dan "dapat menyebabkan beberapa implementasi menolak permintaan dan menutup koneksi karena potensinya sebagai serangan request smuggling". Klien SEBAIKNYA TIDAK menghasilkan konten dalam permintaan HEAD.

Apakah HEAD berguna untuk memeriksa apakah proxy berfungsi?

Sebagian. Permintaan ini memastikan konektivitas dan mengembalikan kode status dengan cepat, yang merupakan uji awal yang baik. Namun, permintaan ini tidak memberi tahu Anda apakah permintaan GET yang sebenarnya akan berhasil, karena lapisan anti-bot sering kali memperlakukan keduanya secara berbeda. Lakukan validasi dengan permintaan GET yang sebenarnya pada sampel sebelum mempercayai hasil HEAD pada seluruh daftar.

Kesimpulan

Hanya dua perintah yang mencakup hal ini sepenuhnya. curl -I URL untuk permintaan HEAD yang benar, dan curl -sS -o /dev/null -D - URL jika Anda ingin melihat header yang dihasilkan oleh permintaan GET sesungguhnya. Yang tidak berfungsi adalah -X HEAD, dan manualnya menjelaskan hal ini dengan jelas: perintah tersebut hanya mengubah kata, bukan perilakunya, sehingga curl menunggu isi (body) yang sebenarnya tidak boleh dikirim oleh server.

Keputusan ada pada Anda, mana di antara keduanya yang Anda inginkan. HEAD jauh lebih efisien — hanya beberapa ratus byte dibandingkan dengan satu halaman penuh — yang menjadikannya alat yang tepat untuk memeriksa tautan, memantau ketersediaan, dan memperkirakan ukuran pada volume apa pun, terutama pada bandwidth yang dibatasi. Ini bukanlah alat yang tepat untuk memprediksi apa yang akan dikembalikan oleh permintaan sebenarnya, karena server diizinkan untuk mengabaikan header yang berasal dari konten, mungkin menolak HEAD secara langsung, dan sering kali mengarahkan permintaan tersebut melalui logika yang berbeda.

Dan jika Anda membutuhkan akurasi GET tanpa menghabiskan bandwidth, -r 0-0 adalah jalan tengah yang jarang digunakan: sebuah GET asli yang hanya mengambil satu byte. Periksa terlebih dahulu Accept-Ranges: bytes, karena banyak server akan memberikan seluruh file tersebut kepada Anda.