วิธีดาวน์โหลดไฟล์ด้วย cURL: Flags, วิธีแก้ปัญหา และสคริปต์

อัปเดตล่าสุดเมื่อ August 11, 2026
Hand-drawn file download flowing from a terminal window into a verified folder
สรุปด้วย AI
คู่มือใช้งาน cURL แบบลงมือทำจริง ครอบคลุมเรื่อง redirect, การยืนยันตัวตน, retry, การดาวน์โหลดต่อจากไฟล์ที่ค้าง, สคริปต์ batch, การตรวจสอบความถูกต้อง และโหมดล้มเหลวที่พบบ่อย

ผมเคยนั่งแก้สคริปต์ตอนดึก ๆ อยู่หลายคืนแบบไม่น่าให้อภัย ทั้งที่มันควรจะแค่ “ดึงไฟล์มาแล้วไปต่อ” เท่านั้น ปรากฏว่าเกือบทุกครั้ง ตัวปัญหาไม่ใช่ cURL พัง แต่เป็น cURL ทำตามที่สั่งเป๊ะ ๆ ไม่ใช่สิ่งที่ผมต้องการจริง ๆ สรุปแล้วช่องว่างระหว่าง “curl -O ใช้ได้” กับ “curl -O ใช้งานได้เสถียรในโปรดักชัน” มันกว้างกว่าที่คิดมาก

คู่มือนี้ถูกเขียนขึ้นมาเพื่อปิดช่องว่างนั้น cURL ติดตั้งมาพร้อมกับ macOS, Linux ส่วนใหญ่ และ Windows 10 ขึ้นไปอยู่แล้ว เท่ากับว่ามีโอกาสสูงมากที่เครื่องคุณมีมันอยู่แล้วตอนนี้ แต่พอเจอปัญหาอย่าง redirect แบบเงียบ ๆ ที่ล้มเหลว, 403 ที่เดาไม่ออก, หรือจาก “ดาวน์โหลดไฟล์เดียว” ไปเป็น “ดาวน์โหลด 500 ไฟล์โดยไม่ทำให้เทอร์มินัลพัง” มันก็มีจุดที่ติดค้างได้ง่ายมาก ผมจะพาไล่ทีละส่วน ทั้ง flags ที่ควรรู้ คำสั่งแบบเป็นขั้นตอนที่ผมใช้จริง ข้อผิดพลาดที่คนพลาดบ่อยที่สุด และจุดที่ cURL ไปต่อไม่ไหวแล้ว — รวมถึงสิ่งที่ควรใช้แทน

cURL คืออะไร และทำไมคุณควรรู้จักมัน?

cURL คือเครื่องมือบรรทัดคำสั่งแบบฟรีและโอเพนซอร์ส สำหรับรับส่งข้อมูลไปยังหรือจากเซิร์ฟเวอร์ผ่าน URL มันรองรับ HTTP, HTTPS, FTP, SFTP และโปรโตคอลอื่น ๆ อีกยาวเป็นหางว่าว จึงโผล่ให้เห็นได้ตั้งแต่ในสคริปต์ bash, Dockerfile ไปจนถึง CI pipeline เบื้องหลัง คำสั่ง curl ที่คุณพิมพ์ในเทอร์มินัลจะใช้ libcurl ซึ่งเป็นไลบรารีภาษา C สำหรับงานรับส่งข้อมูลที่หลายแอปพลิเคชันและหลาย language binding ฝังเอาไว้ เช่น ส่วนขยาย cURL ของ PHP เป็นตัวอย่างหนึ่ง ขณะที่ Requests ของ Python เป็น HTTP client อีกตัวหนึ่งที่สร้างบน urllib3 ไม่ได้ใช้ libcurl

เวอร์ชันเสถียรล่าสุด ณ ตอนเขียนคือ curl 8.21.0 ซึ่งออกในเดือนมิถุนายน 2026 — แต่อย่าเพิ่งคิดว่า OS ของคุณจะติดตั้งบิลด์นี้มาด้วยเลย เวอร์ชันที่มากับดิสโทรมักจะตามหลัง upstream อยู่หลายเดือน หรือบางทีก็นานกว่านั้น ดังนั้นควรรัน curl --version ก่อนจะสรุปว่ามี flag อย่าง --parallel ให้ใช้แน่ ๆ

ทำไมต้องดาวน์โหลดไฟล์ด้วย cURL? กรณีใช้งานยอดนิยม

มีคนถามผมบ่อยเหมือนกันว่า ทำไมต้องใช้เครื่องมือบรรทัดคำสั่ง ทั้งที่เบราว์เซอร์ก็ดาวน์โหลดไฟล์ได้อยู่แล้ว คำตอบจริง ๆ คือ: เบราว์เซอร์ดีมาก จนกระทั่งคุณต้องการทำให้มันอัตโนมัติ

กรณีใช้งานจุดเด่นของ cURL
ดาวน์โหลดไฟล์ไบนารีใน CI/CD pipelineสั่งผ่านสคริปต์ได้ ไม่ต้องใช้ GUI
ดึง API response หรือไฟล์ export ของข้อมูลรองรับ header แบบกำหนดเอง, auth, และการส่งต่อเอาต์พุต
ดาวน์โหลดไฟล์ขนาดใหญ่ต่อจากจุดที่ค้างผ่าน SSHมีระบบ resume ในตัว (-C -)
ทำงานดาวน์โหลดซ้ำตามรอบอัตโนมัติ (cron job)เบา และต่อกับ shell script ได้ดี
ดึงไฟล์ที่ต้องยืนยันตัวตนก่อนเข้าถึงมีตัวเลือก auth ที่ยืดหยุ่น (basic, token, cookies, .netrc)

การดาวน์โหลดผ่านเบราว์เซอร์คือการกดแบบครั้งเดียวจบ ส่วน cURL เปลี่ยนการทำงานแบบเดิมให้กลายเป็นสิ่งที่คุณตั้งเวลาได้ ต่อเข้ากับ pipeline ได้ ลองใหม่เมื่อพลาดได้ และรันเหมือนกันได้เป็นร้อยเซิร์ฟเวอร์พร้อมกัน นั่นแหละเสน่ห์ของมัน — ไม่ได้หวือหวากว่า แค่ทำซ้ำได้

Hand-drawn flow from a web source to a downloaded file and local folder

Flags สำคัญของ cURL สำหรับการดาวน์โหลดไฟล์

ผมมักกลับมาใช้ flags ชุดเดิมราวสิบกว่าตัวอยู่เสมอสำหรับงาน 90% ที่ทำอยู่ นี่คือ cheat sheet ที่ผมหวังว่าใครสักคนจะยื่นให้ผมตั้งแต่เมื่อหลายปีก่อน แยกตามหน้าที่จริง ๆ ของมัน

Flags สำหรับกำหนดเอาต์พุตและการบันทึกไฟล์

  • -O (--remote-name) บันทึกไฟล์โดยใช้ชื่อจากท้าย URL เป็นชื่อไฟล์ สะดวกดี แต่ก็อาจเขียนทับไฟล์เดิมที่ชื่อซ้ำกันได้แบบไม่เตือน
  • -o <filename> (--output) ให้คุณกำหนดชื่อไฟล์ปลายทางเองได้ชัดเจน: curl -o report.pdf https://example.com/downloads/file.pdf
  • -J (--remote-header-name) ใช้ชื่อไฟล์จาก header Content-Disposition ของเซิร์ฟเวอร์แทนชื่อจาก URL ตัวนี้สะดวกมากสำหรับดาวน์โหลดจาก API แต่ควรมองชื่อไฟล์จากฝั่งเซิร์ฟเวอร์ว่าไม่น่าเชื่อถือ — ควรดาวน์โหลดลงโฟลเดอร์เฉพาะ ไม่ใช่โฟลเดอร์บ้านของคุณ ตามคำแนะนำด้านความปลอดภัยของ curl เอง

Flags ด้านพฤติกรรมที่ทุกการดาวน์โหลดควรมี

  • -L (--location) สั่งให้ curl ตาม HTTP redirect ถ้าไม่มีตัวนี้ การตอบกลับแบบ 3xx จะถูกบันทึกเป็นหน้า HTML redirect ขนาดจิ๋วแทนไฟล์จริง ซึ่งเป็นความผิดพลาดที่ผมเจอบ่อยที่สุดแบบ “ทำไมดาวน์โหลดแล้วพัง”
  • -C - (--continue-at -) ใช้ดาวน์โหลดต่อจากจุดที่หยุดค้างไว้
  • -s / -S ทำงานแบบเงียบ แต่ยังแสดง error อยู่ — เหมาะกับสคริปต์ที่ไม่อยากให้ progress bar ไปรก log
  • --limit-rate 1M จำกัดความเร็วการใช้แบนด์วิดท์ (มีประโยชน์บนเครือข่ายร่วมใช้ หรือเวลาที่ไม่อยากกินเน็ต metered มากเกินไป)
  • --connect-timeout 10 และ --max-time 300 ป้องกันการเชื่อมต่อค้างจนสคริปต์หยุดคาอยู่ตลอด
  • --retry 3 และ --retry-delay 5 ลองใหม่อัตโนมัติเมื่อเจอความล้มเหลวชั่วคราว — ตาม curl man page ควรจับคู่กับ --retry-all-errors เฉพาะตอนที่การส่งคำขอเดิมซ้ำปลอดภัยจริง ๆ เท่านั้น

Flags สำหรับแสดงความคืบหน้าและดีบัก

  • -# แสดง progress bar แบบง่าย แทนตารางสถิติเริ่มต้น
  • -v แสดงรายละเอียด verbose รวมถึง header ของ request/response แบบครบ ๆ — เป็นตัวที่ผมใช้ประจำเวลาอะไรเริ่มงอแง
  • -I (--head) ดึงเฉพาะ response headers เป็นเช็กก่อนเริ่มดาวน์โหลดก้อนใหญ่ได้ดีมาก
  • -w ให้พิมพ์เอาต์พุตแบบกำหนดเองหลังจบการรับส่ง เช่น curl -o /dev/null -s -w "%{http_code}\n" <url> เพื่อเช็กแค่ status code

ก่อนเริ่มต้น

  • ระดับความยาก: มือใหม่ถึงระดับกลาง (ส่วน batch และ auth จะยกระดับขึ้นนิดหน่อย)
  • เวลาที่ใช้: ประมาณ 15-20 นาทีสำหรับไล่คำสั่งหลักให้ครบ
  • สิ่งที่ต้องมี: เทอร์มินัล (macOS Terminal, Linux shell หรือ Windows PowerShell/WSL), ติดตั้ง curl แล้ว (เช็กด้วย curl --version) และ URL สำหรับทดสอบ — ผมจะใช้ GitHub release asset แบบสาธารณะเป็นตัวอย่าง เพราะเสถียรและเข้าถึงได้ฟรี

วิธีดาวน์โหลดไฟล์ด้วย cURL แบบทีละขั้นตอน

ขั้นที่ 1: ดาวน์โหลดไฟล์เดี่ยว

พื้นฐานที่สุด: curl -O <url> จะบันทึกไฟล์ด้วยชื่อเดิมจากปลาย URL ส่วน curl -o myfile.zip <url> ให้คุณเปลี่ยนชื่อไฟล์ตอนดาวน์โหลดได้

curl -LO https://github.com/curl/curl/releases/download/curl-8_21_0/curl-8.21.0.tar.gz

ตอนนี้ผมใส่ -L เป็นค่าเริ่มต้นเสมอ ไม่มีข้อยกเว้น — ผมเคยเจ็บมาแล้วหลายครั้งจาก redirect ที่เงียบ ๆ ทำให้สิ่งที่คิดว่าเป็น “ไฟล์ดาวน์โหลด” กลายเป็น HTML ขนาด 400 ไบต์ คุณควรเห็นตัวนับความคืบหน้าไหลขึ้นในเทอร์มินัล แล้วไฟล์จะไปอยู่ในไดเรกทอรีปัจจุบันของคุณ

เมื่อคำสั่งสำเร็จ progress meter จะไปถึง 100% และ curl-8.21.0.tar.gz จะปรากฏในโฟลเดอร์ปัจจุบัน ตรวจสอบไฟล์ก่อนนำไปใช้:

ls -lh curl-8.21.0.tar.gz

ขั้นที่ 2: ดาวน์โหลดแล้วเปลี่ยนชื่อไฟล์

ใช้ -o เมื่อคุณต้องการชื่อไฟล์ปลายทางเฉพาะ แทนชื่อที่ URL ลงท้ายมาให้:

curl -L -o curl-latest.tar.gz -S https://github.com/curl/curl/releases/download/curl-8_21_0/curl-8.21.0.tar.gz

-S ในที่นี้ช่วยเปิดการแสดง error กลับมา เผื่อว่าคุณจะใส่ -s ไว้ในสคริปต์ส่วนอื่นด้วย ชุดคำสั่ง -L -o <name> -S นี้แทบจะเป็นคำสั่งดาวน์โหลดไฟล์เดี่ยวประจำของผมเลย

ขั้นที่ 3: ดาวน์โหลดต่อจากไฟล์ที่หยุดค้าง

ถ้าดาวน์โหลดไฟล์ใหญ่แล้วหลุดกลางทาง (Wi‑Fi แย่, VPN กระตุก หรืออะไรก็ตาม) อย่าเริ่มใหม่ทั้งหมด ให้รัน:

curl -C - -LO https://example.com/large-file.iso

ข้อควรระวังคือ วิธีนี้จะใช้ได้ก็ต่อเมื่อเซิร์ฟเวอร์รองรับ byte-range request เท่านั้น Accept-Ranges: bytes เป็นสัญญาณบวกที่มีประโยชน์ แต่การไม่มีมันไม่ได้แปลว่าระบบไม่รองรับ range แน่ ๆ วิธีเช็กที่เชื่อถือได้คือดูการตอบกลับจริงจาก range request: ถ้า resume ได้ปกติ มักจะตอบกลับ 206 Partial Content พร้อม Content-Range ที่ถูกต้อง ลองรันคำสั่ง resume แล้วตรวจสถานะด้วย -v หรือ -D -; ถ้าเซิร์ฟเวอร์ไม่สนใจ range หรือปฏิเสธ offset ให้เริ่มใหม่อย่างตั้งใจ แทนที่จะเดาว่าไฟล์บางส่วนปลอดภัย

A resilient cURL download resumes after interruption and finishes with checksum verification

ขั้นที่ 4: ดาวน์โหลดพร้อมแถบความคืบหน้า หรือแบบเงียบ ๆ

ถ้าอยากให้ดูสะอาดในเทอร์มินัลแบบโต้ตอบ: curl -# -LO <url> ถ้าใช้กับสคริปต์และ cron job ที่อยากได้แค่ error ไม่อยากได้เสียงรบกวน: curl -sS -LO <url> ผมใช้แบบเงียบเกือบตลอด ยกเว้นตอนดีบักด้วยตัวเอง

ขั้นที่ 5: จำกัดความเร็วในการดาวน์โหลด

บนเครือข่ายสำนักงานที่แชร์กันหลายคน (หรือเวลาที่ผมไม่อยากเป็น “คนนั้น” ที่แย่งแบนด์วิดท์ตอนประชุมวิดีโอ) ผมจะจำกัดความเร็วแบบนี้:

curl --limit-rate 1M -LO https://example.com/big-dataset.zip

หน่วยคือ K, M, และ G สำหรับ kilobytes, megabytes, และ gigabytes ต่อวินาที ตามลำดับ

ขั้นที่ 6: บันทึก response headers ไว้คู่กับไฟล์

บางครั้งผมต้องการรู้ว่าเซิร์ฟเวอร์ตอบอะไรมาบ้างแบบเป๊ะ ๆ — content type, cache headers และเรื่องอื่น ๆ — โดยไม่ทำให้เทอร์มินัลรก:

curl -L -D headers.txt -o file.zip https://example.com/file.zip

คำสั่งนี้จะเก็บ response headers ไว้ใน headers.txt ขณะที่ไฟล์จริงจะถูกบันทึกเป็น file.zip เหมาะมากสำหรับดีบักปัญหา content-type ไม่ตรง หรือเช็กว่า CDN แคชข้อมูลตามที่คุณคิดไว้จริงไหม

เคล็ดลับและข้อผิดพลาดที่พบบ่อย

  • เคล็ดลับ: ตั้ง -L เป็นค่าเริ่มต้นเสมอ ผมนึกไม่ออกจริง ๆ ว่ามันมีข้อเสียอะไร และผมเสียเวลากับการลืมใส่มันมาหลายชั่วโมงแล้ว
  • เคล็ดลับ: เวลาเขียนสคริปต์ ให้จับคู่ --fail กับคำสั่งดาวน์โหลดด้วย เพื่อให้ response ที่ไม่ใช่ 2xx ทำให้สคริปต์จบพร้อม error จริง ๆ แทนที่จะบันทึก error page แบบเงียบ ๆ ราวกับเป็นไฟล์ที่ถูกต้อง
  • ข้อผิดพลาด: อย่าใช้ -C - คู่กับ --remove-on-error เพราะ curl ระบุว่าทั้งสองอย่างไม่เข้ากัน เนื่องจากการ resume ต้องอาศัยไฟล์บางส่วนเดิมยังอยู่
  • ข้อผิดพลาด: -O สามารถเขียนทับไฟล์ได้โดยไม่เตือน ถ้าคุณดาวน์โหลดหลายไฟล์ลงโฟลเดอร์ที่ใช้ร่วมกัน ควรใช้ --output-dir เพื่อกันไฟล์ไว้เป็นที่

วิธีดาวน์โหลดหลายไฟล์และทำ batch download ด้วย cURL

ตัวอย่างไฟล์เดี่ยวเป็นส่วนที่ง่าย ส่วน workflow จริงที่ผมสร้างขึ้นมา — เช่น ดึงข้อมูล export ทุกคืน หรือซิงก์ไบนารีข้าม build server — ต้องใช้ concurrency และนี่คือจุดที่บทความส่วนใหญ่จบแบบดื้อ ๆ มีอยู่ 3 วิธีที่ควรรู้ โดยแต่ละวิธีก็ซับซ้อนขึ้นทีละนิด

วิธีที่ 1: ใส่หลาย URL ใน cURL คำสั่งเดียว

วิธีที่ง่ายที่สุดคือแค่ระบุ URL หลายตัว:

curl -LO https://example.com/a.zip -LO https://example.com/b.zip -LO https://example.com/c.zip

วิธีนี้ใช้ได้ แต่จะทำแบบเรียงลำดับ — curl จะดาวน์โหลดไฟล์หนึ่งให้เสร็จก่อนแล้วค่อยเริ่มไฟล์ถัดไป ไหวสำหรับ 3 ไฟล์ แต่ทรมานสำหรับ 300 ไฟล์

วิธีที่ 2: ดาวน์โหลดแบบขนานด้วย --parallel (curl 7.66+)

ตั้งแต่ curl 7.66 เป็นต้นมา คุณสามารถเพิ่ม --parallel (หรือ -Z) เพื่อดึงหลาย URL พร้อมกันได้:

curl --parallel --parallel-max 5 --remote-name-all \
  https://example.com/a.zip https://example.com/b.zip https://example.com/c.zip

สิ่งที่ควรรู้คือ ค่า parallel max เริ่มต้นจริง ๆ คือ 50 ซึ่งเป็นจำนวนการเชื่อมต่อพร้อมกันที่มากเกินกว่าจะได้คำขอบคุณจากเซิร์ฟเวอร์ส่วนใหญ่ หรือจากเครือข่ายของคุณเอง ผมมักกำหนด --parallel-max เองแบบระวัง ๆ — โดยทั่วไปอยู่ที่ 4 ถึง 8 — แทนที่จะปล่อยตามค่า default

วิธีที่ 3: ใช้ xargs และ Bash loop เพื่อทำ concurrency จากรายการ URL

ถ้ามีรายการ URL จำนวนมากอยู่ในไฟล์ข้อความ ผมมักใช้ xargs:

cat urls.txt | xargs -n1 -P 8 curl -O -L

หรือถ้าอยากควบคุมงานของแต่ละรอบให้มากขึ้น จะใช้ bash loop ที่รันเป็น background process:

while read -r url; do
  curl -O -L "$url" &
done < urls.txt
wait

wait ท้ายสุดสำคัญมาก — ถ้าไม่มีมัน สคริปต์จะออกก่อนที่การดาวน์โหลดพื้นหลังจะเสร็จ

เมื่อไหร่ควรใช้ wget หรือ aria2 แทน

พูดตรง ๆ เลย: cURL ไม่ใช่เครื่องมือที่เหมาะทุกกรณี ถ้าคุณต้องการ mirror โครงสร้างไดเรกทอรีทั้งเว็บไซต์ wget -r จะทำ recursive crawling ได้ในตัว ในแบบที่ cURL ไม่ได้ออกแบบมาเพื่อสิ่งนี้ ถ้าคุณต้องการดาวน์โหลดไฟล์ขนาดใหญ่มากแบบ multi-source และแบ่งส่วนเพื่อเอาความเร็วสูงสุด aria2c จะเร็วกว่าจริง

เครื่องมือเหมาะที่สุดสำหรับ
cURLความแม่นยำ, การเขียนสคริปต์, ดาวน์โหลดไฟล์เดี่ยวหรือชุดเล็ก, การโต้ตอบกับ API
wgetดาวน์โหลดเว็บไซต์แบบ recursive/mirror, ดึงไฟล์สาธารณะจำนวนมากแบบง่าย ๆ
aria2ดาวน์โหลดแบบ multi-source/segmented, ดันความเร็วสูงสุดสำหรับไฟล์ใหญ่

จุดแข็งของ cURL คือความแม่นยำและการประกอบต่อกันได้ดี — การ pipe, การเขียนสคริปต์, ความยืดหยุ่นของโปรโตคอล — ไม่ใช่การไล่เก็บแบบ brute force

วิธีดาวน์โหลดไฟล์ที่ต้องยืนยันสิทธิ์ด้วย cURL: รูปแบบการทำ auth

บทความ cURL ส่วนใหญ่มักหยุดที่ -u user:pass แล้วก็จบ นั่นเป็นแนวคิดจากยุคอินเทอร์เน็ตก่อนเก่า แต่ในปี 2026 ไฟล์ที่ผมดาวน์โหลดจริงมักมาจาก REST API, dashboard ที่ใช้ session, และระบบ CI — ซึ่งแต่ละอย่างต้องใช้ credential คนละแบบ

Basic Auth

curl -u username:password -O https://legacy-server.example.com/file.zip

ใช้ได้ดีกับเซิร์ฟเวอร์ FTP แบบเก่าหรือ HTTP endpoint ทั่วไป แต่ต้องรู้ไว้ว่ารหัสผ่านจะโผล่ใน shell history และ process list ถ้าไม่ระวัง — ซึ่งผมไม่แนะนำให้ใช้กับอะไรที่ละเอียดอ่อน

Bearer / OAuth Token Auth

นี่คือรูปแบบที่ในคู่มือจำนวนมากแทบไม่ค่อยพูดถึง ทั้งที่ผมใช้งานบ่อยที่สุดตอนนี้:

curl -H "Authorization: Bearer $GITHUB_TOKEN" \
  -LO https://api.github.com/repos/curl/curl/releases/assets/12345

นี่เป็นแพตเทิร์นจริงสำหรับดึง GitHub release asset แบบ private — แค่เปลี่ยน token กับ asset ID ของคุณ REST API และ resource ที่ป้องกันด้วย OAuth2 ส่วนใหญ่ในปัจจุบันพูดภาษานี้กันทั้งนั้น

Cookie-Based Session Auth

สำหรับเว็บแอปที่ล็อกอินแล้วสร้าง session ให้บันทึก cookie jar ตอนล็อกอิน และนำกลับมาใช้ตอนดาวน์โหลด:

curl -c cookies.txt -d "user=me&pass=secret" https://example.com/login
curl -b cookies.txt -O https://example.com/protected/file.zip

ไฟล์ .netrc สำหรับงานสคริปต์และ CI

นี่คือวิธีที่ผมชอบที่สุดสำหรับงานที่รันแบบไม่ต้องเฝ้าเอง สร้างไฟล์ ~/.netrc (หรือ _netrc บน Windows):

machine example.com
login myusername
password mypassword

ล็อกสิทธิ์ไฟล์ด้วย chmod 600 ~/.netrc แล้วเรียกใช้งานแบบนี้:

curl --netrc -LO https://example.com/protected-file.zip

ข้อดีคือ credential จะไม่ไปอยู่ใน shell history หรือ source ของสคริปต์ ซึ่งสำคัญจริง ๆ ใน CI/CD ที่มักจะมีการ log สคริปต์แบบเต็มบรรทัด

วิธี authFlag/ตัวเลือกเหมาะที่สุดสำหรับ
Basic auth-u user:passFTP แบบเก่า, HTTP ทั่วไป
Bearer token-H "Authorization: Bearer <token>"REST API, OAuth2
Cookie auth-b cookies.txt (+ -c เพื่อบันทึก)เว็บแอปที่ใช้ session
ไฟล์ .netrc--netrc หรือ --netrc-fileCI/CD, สภาพแวดล้อมที่รันด้วยสคริปต์

Hand-drawn progress blocks, retry arrow, and completed folder

การแก้ปัญหา cURL ดาวน์โหลดไม่สำเร็จที่พบบ่อย

นี่คือส่วนที่ผมอยากให้มีตอนเริ่มต้นมากที่สุด เพราะแทบไม่มีใครอธิบายไว้ครบ “ทำไม curl ดาวน์โหลดไม่ได้” เป็นคำค้นหาที่เจอบ่อยและหงุดหงิดมาก และวิธีแก้ส่วนใหญ่ก็เป็นคำสั่งสั้น ๆ แค่บรรทัดเดียว ถ้ารู้สาเหตุแล้ว

อาการสาเหตุที่เป็นไปได้วิธีแก้
curl: (60) SSL certificate problemใบรับรอง self-signed หรือหมดอายุ--cacert <file> หรือ -k (ใช้เฉพาะ dev)
403 Forbidden / ไฟล์ว่างเซิร์ฟเวอร์บล็อก user agent เริ่มต้นของ curl-A "Mozilla/5.0..." หรือ -H "User-Agent: ..."
ดาวน์โหลดเริ่มใหม่จาก 0 ตอนใช้ -C -เซิร์ฟเวอร์ไม่รองรับ Rangeเช็กด้วย curl -I <url> และดู Accept-Ranges: bytes
บันทึกไฟล์ขนาด 0 ไบต์ไม่ได้ตาม redirectเพิ่ม flag -L
curl: (28) Operation timed outเซิร์ฟเวอร์ช้า หรือเน็ตมีปัญหา--connect-timeout 10 --max-time 300 + --retry 3
บันทึกเป็นหน้า HTML แทนไฟล์จริงหน้านั้นต้องใช้ JavaScript ในการเรนเดอร์curl ใช้ JavaScript ไม่ได้ — ดูส่วนด้านล่าง

ข้อผิดพลาด SSL Certificate: หมายความว่าอะไร และจะแก้ยังไง

Error 60 หมายความว่า curl ยืนยันใบรับรอง SSL ของเซิร์ฟเวอร์ไม่ได้ — โดยทั่วไปเพราะเป็น self-signed, หมดอายุ, หรือออกโดย CA ที่ curl ไม่ไว้ใจ ถ้าคุณควบคุมเซิร์ฟเวอร์เอง ให้ชี้ curl ไปยัง CA bundle ที่ถูกต้องด้วย --cacert /path/to/ca.pem ส่วน -k (--insecure) จะข้ามการตรวจสอบทั้งหมด ซึ่งพอใช้ได้ในสภาพแวดล้อม dev ในเครื่อง แต่เป็นความคิดที่แย่มากถ้าเกี่ยวข้องกับ production หรือข้อมูลผู้ใช้จริง

403 Forbidden และการดาวน์โหลดที่ว่างเปล่า

เซิร์ฟเวอร์จำนวนไม่น้อยบล็อกคำขอที่ระบุตัวเองว่าเป็น curl/8.21.0 (User-Agent เริ่มต้นของ curl) เพราะคิดว่าเป็นบอทหรือสแครปเปอร์ วิธีแก้ส่วนใหญ่คือแกล้งทำเป็นเบราว์เซอร์:

curl -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" -LO https://example.com/file.zip

ถ้าอยากเช็กว่าจริง ๆ แล้วเซิร์ฟเวอร์ตอบอะไรกลับมาก่อนจะดาวน์โหลดเต็ม ผมใช้: curl -o /dev/null -s -w "%{http_code}\n" <url>

Timeout, Retry และการเชื่อมต่อที่ไม่นิ่ง

นี่คือคำสั่งที่ผมอยากสักไว้บนแขน ถ้าผมกล้าพอจะสักจริง

คำสั่งดาวน์โหลดประจำของผม ซึ่งใช้ในสคริปต์โปรดักชันจริง ๆ จะรวม flags ด้านความเสถียรเข้าด้วยกันทั้งหมด:

curl -L -C - --retry 5 --retry-delay 3 --connect-timeout 10 --max-time 600 --fail -O <url>

มันคือการตาม redirect, resume, retry 5 ครั้งเว้น 3 วินาที, timeout การเชื่อมต่อ 10 วินาที, จำกัดเวลารวม 10 นาที, และ fail ทันทีเมื่อ HTTP status ไม่ดี — เรียกว่ารวมทุกอย่างที่ผมเรียนรู้มาด้วยความเจ็บปวดเอาไว้หมดแล้ว

cURL ในระบบอัตโนมัติจริง: CI/CD pipeline, การ pipe และความปลอดภัยของสคริปต์

ส่งเอาต์พุตของ cURL ไปยังเครื่องมืออื่นผ่าน pipe

curl ไม่จำเป็นต้องบันทึกอะไรลงดิสก์เลยด้วยซ้ำ — การส่งต่อไปยังคำสั่งอื่นโดยตรงเป็นหนึ่งในความสามารถที่คนมักมองข้ามมากที่สุด:

curl -sL https://example.com/archive.tar.gz | tar xz
curl -s https://api.example.com/data | jq '.results'

ดาวน์โหลดแล้วแตกไฟล์ หรือดาวน์โหลดแล้ว parse ในบรรทัดเดียว นี่คือแพตเทิร์นที่ผมใช้บ่อยมากสำหรับการดึงข้อมูลแบบครั้งคราว

ใช้ cURL ใน GitHub Actions และ CI/CD

ตัวอย่างขั้นตอน GitHub Actions แบบเรียบง่ายที่ดาวน์โหลด binary พร้อม logic สำหรับ retry และ fail ชัดเจนเมื่อเกิดปัญหา:

- name: Download binary
  run: |
    curl -L --fail --retry 3 --retry-delay 5 \
      -o app-binary "https://example.com/releases/app-binary"

ให้เก็บ token ไว้เป็น CI secret แล้วเรียกผ่าน environment variable — อย่า hardcode ลงในสคริปต์โดยตรง และใช้ --fail (หรือ --fail-with-body ถ้าคุณต้องการเห็น error body สำหรับดีบัก) เพื่อให้การดาวน์โหลดที่เสียจริง ๆ ทำให้ build ล้มจริง แทนที่จะผ่านแบบเงียบ ๆ พร้อมข้อมูลขยะ

คำถามด้านความปลอดภัยของ curl | sh

เรื่องนี้โผล่ในแทบทุกฟอรัมของนักพัฒนาที่ผมเคยอ่านมา และมีเหตุผลชัดเจน: การ pipe curl เข้า sh โดยตรงหมายถึงการรันโค้ดจากระยะไกลที่คุณยังไม่ได้ตรวจดู โดยอิงแค่ความเชื่อว่าเซิร์ฟเวอร์ไม่ได้ถูกเจาะ และการเชื่อมต่อไม่ได้ถูกดัดแปลง นั่นแหละคือความเสี่ยงจริง ๆ — ไม่ใช่ความระแวง แต่เป็นความเสี่ยงด้าน supply chain แบบตรงไปตรงมา

แพตเทิร์นที่ปลอดภัยกว่าคือดาวน์โหลดมาก่อน ตรวจดูสคริปต์ ตรวจสอบ checksum หรือ GPG signature ถ้ามีให้ แล้วค่อยรัน:

curl -sL https://example.com/install.sh -o install.sh
cat install.sh   # อ่านจริง ๆ ก่อน
sha256sum install.sh   # เทียบกับ checksum ที่เผยแพร่ ถ้ามี
bash install.sh

ตัวติดตั้งที่เป็นที่รู้จักอย่าง rustup และ Homebrew ก็ยังใช้แพตเทิร์น curl | sh อยู่ และโดยทั่วไปก็ยอมรับกันได้ในกรณีเฉพาะนั้น เพราะผู้ดูแลและช่องทางแจกจ่ายมีความน่าเชื่อถือสูง แต่ผมก็ยังอยากเสียเวลาเพิ่มอีกสิบวินาทีเพื่ออ่านสคริปต์ ดีกว่ามาเสียใจทีหลัง

เมื่อ cURL ยังไม่พอ: หน้าเว็บที่เรนเดอร์ด้วย JS, เว็บไซต์กันบอท และข้อมูลแบบมีโครงสร้าง

นี่คือความล้มเหลวแบบหนึ่งที่ทำให้หลายคนงง และส่วนใหญ่ไม่ใช่ความผิดของเขาด้วย: คุณสั่ง curl -O ไปที่หน้าที่ดูเหมือนเว็บธรรมดา แต่แทนที่จะได้เนื้อหาที่คาดไว้ กลับได้ HTML เปล่า ๆ, หน้า challenge ของ Cloudflare, หรืออะไรที่ดูไร้ระเบียบ curl ทำสิ่งที่มันถูกออกแบบมาให้ทำอย่างถูกต้องแล้ว — มันแค่ดึง raw HTTP response แต่ curl ไม่สามารถรัน JavaScript, แก้ CAPTCHA, หรือฝ่าระบบ fingerprinting ป้องกันบอทได้ สิ่งเหล่านั้นไม่ใช่บั๊กของ curl เลย แต่เป็นงานที่อยู่นอกขอบเขตหน้าที่ของมันทั้งหมด

ทำไม cURL ถึงล้มเหลวบนหน้าเว็บยุคใหม่

เว็บแอปแบบ single-page จำนวนมากส่งกลับมาแค่ HTML skeleton ที่แทบว่างเปล่า แล้วให้ JavaScript เรนเดอร์เนื้อหาจริงฝั่ง client หลังโหลดหน้าเสร็จ — ซึ่ง curl ไม่มีทางรันส่วนนี้ได้ นอกจากนี้ ระบบอย่าง Cloudflare และ Akamai ยังเสิร์ฟ challenge page ให้กับอะไรก็ตามที่ไม่ดูเหมือนเบราว์เซอร์จริง และคำขอ curl ซ้ำ ๆ จาก IP เดิมก็อาจถูกจำกัดอัตราหรือถูกจัดว่าเป็นทราฟฟิกจากบอทได้เร็วมาก

ก้าวต่อไป: AI Scraping API สำหรับนักพัฒนา

ถ้าถามผม cURL เหมาะกับราว 80% ของงานดาวน์โหลดไฟล์และข้อมูลทั้งหมดที่มีอยู่ — asset แบบสแตติก, API response, อะไรก็ตามที่เสิร์ฟเป็น resource HTTP ปกติ ส่วนอีก 20% ที่เป็นหน้าหนัก JavaScript หรือมีการป้องกันบอท คือจุดที่ผมเห็นนักพัฒนาเสียเวลาหลายชั่วโมงไปกับการสู้ header และ user-agent ก่อนจะยอมแพ้และเปลี่ยนไปใช้ชั้นเครื่องมือแบบอื่น

นั่นแหละคือช่องว่างที่ทีมของเราออกแบบ Thunderbit มาเพื่อเติมเต็ม ควบคู่ไปกับ Chrome extension ที่หลายคนรู้จักเราอยู่แล้ว ฝั่งนักพัฒนา Thunderbit มี Open API ที่ให้ POST /distill ซึ่งส่งกลับ Markdown ที่สะอาด พร้อมใช้งานกับ LLM จาก URL โดยให้บริการเรนเดอร์หน้าเว็บให้เรียบร้อย และ POST /extract ที่ส่งกลับ structured JSON ตาม schema เมื่อคุณต้องการข้อมูลแบบมีฟิลด์จริง ๆ แทนข้อความที่อ่านง่าย นอกจากนี้ยังมี MCP server ให้เอเจนต์ใน Claude หรือ Cursor เรียก thunderbit_distill และ thunderbit_extract ระหว่างทำงานได้ และมี CLI (npx @thunderbit/thunderbit-cli distill <url>) ที่ให้ประสบการณ์คล้าย curl ในเทอร์มินัลของคุณ คุณสามารถ pipe เอาต์พุต JSON ไปยัง jq ได้ เช่น thunderbit distill <url> --format json | jq -r '.data.markdown'; หรือส่งเอาต์พุต --format markdown ไปยังเครื่องมือจัดการข้อความหรือบันทึกลงไฟล์แทน

ถ้าเทียบกันชัด ๆ ความต่างเห็นได้เลย คำขอ curl ไปยังหน้า product ที่เรนเดอร์ด้วย JS อาจคืนค่าเป็น <div id="root"></div> ที่เกือบว่างเปล่า แต่คำสั่ง thunderbit distill ที่เทียบเท่ากันจะคืนเนื้อหาหน้าเว็บเป็น Markdown ที่สะอาด Distill ใช้ 1 เครดิตต่อ URL และ Extract ใช้ 20 เครดิตต่อ URL ขีดจำกัดของแต่ละ endpoint ในปัจจุบันก็แตกต่างกัน: Batch Distill รองรับได้ถึง 100 URL ต่อหนึ่งงาน ขณะที่ Batch Extract รับได้สูงสุด 50 URL ด้วย schema เดียวกัน ควรตรวจเอกสาร API ล่าสุดก่อนวางขนาดคิวงานในโปรดักชัน

ถ้าคุณยังใหม่กับแนวคิดนี้ บทความอธิบายของเราเรื่อง web scraping คืออะไรจริง ๆ เป็นจุดเริ่มต้นที่ดี และ คู่มือ scraping แบบไม่ต้องเขียนโค้ด จะอธิบายอีกมุมหนึ่งของปัญหาเดียวกันสำหรับคนในทีมที่ไม่อยากแตะเทอร์มินัล สำหรับการเทียบเครื่องมือในตลาดแบบกว้างขึ้น เรายังรวบรวม AI web scraper ที่ดีที่สุด ไว้อ่านประกอบด้วย

สรุปด่วน: cheat sheet สำหรับดาวน์โหลดด้วย cURL

งานคำสั่ง
ดาวน์โหลดพื้นฐานcurl -LO <url>
ตั้งชื่อไฟล์เองcurl -L -o myfile.zip <url>
ดาวน์โหลดต่อจากไฟล์ที่ค้างcurl -C - -LO <url>
เงียบ แต่ยังแสดง errorcurl -sSL -O <url>
ดาวน์โหลดแบบขนานcurl --parallel --parallel-max 5 -O <url1> -O <url2>
ใช้ Bearer token authcurl -H "Authorization: Bearer <token>" -LO <url>
คำสั่งดาวน์โหลดสำหรับสคริปต์ที่ผมใช้บ่อยcurl -LO --retry 5 --retry-delay 3 --max-time 600 --fail <url>
pipe ไปยังเครื่องมือแยกข้อมูลcurl -sL <url> | tar xz

บทสรุปและประเด็นสำคัญ

การดาวน์โหลดไฟล์ด้วย curl เริ่มต้นง่าย — แค่ curl -O ก็แทบจบแล้ว — แต่ทักษะจริงอยู่ในชั้นถัดลงไป: รู้ว่าเมื่อไหร่ต้องเติม -L, เมื่อไหร่ควร resume แทนเริ่มใหม่, auth แบบไหนเข้ากับ workflow ของคุณจริง ๆ, และควรทำอย่างไรเมื่อ 403 หรือ HTML เปล่า ๆ โผล่มาแทนไฟล์ที่หวังไว้ ผมเคยพึ่งทุกแพตเทิร์นที่ว่ามานี้มาแล้วสักครั้งหนึ่ง โดยมากคือหลังจากเรียนรู้บทเรียนแบบเจ็บ ๆ ว่ามันสำคัญแค่ไหน

cURL ยังคงเป็นเครื่องมือหลักของผมสำหรับการดาวน์โหลดไฟล์ตรงไปตรงมาและงาน HTTP ที่เขียนสคริปต์ได้ — มันเร็ว มีอยู่แทบทุกที่ และต่อเข้ากับ shell pipeline อื่น ๆ ได้อย่างสวยงาม แต่เมื่อคุณเจอหน้าเว็บที่เรนเดอร์ด้วย JavaScript หรือกำแพงกันบอท นั่นไม่ใช่ปัญหาที่จะโซ้ยด้วย flags เพิ่มอีกนิด แต่มันคือสัญญาณว่าคุณต้องใช้ชั้นเครื่องมืออีกแบบ และนั่นคือจุดที่ API อย่าง Thunderbit เข้ามารับช่วงต่อ โดยไม่บังคับให้คุณต้องออกจากเทอร์มินัล

บันทึก cheat sheet นี้ไว้ ลองคำสั่ง retry-and-resume ในการดาวน์โหลดครั้งหน้าที่ไม่เสถียร และถ้าคุณเจอกำแพงที่ cURL คืนข้อมูลขยะออกมาแทน คุณก็รู้แล้วว่าก้าวต่อไปหน้าตาเป็นยังไง — หน้า pricing ของ Thunderbit มีรายละเอียดเครดิตล่าสุด ถ้าคุณอยากดูว่าการยกระดับไปใช้แบบนั้นต้องจ่ายเท่าไร และ ช่อง YouTube ของเราก็มีวิดีโอ walkthrough ถ้าคุณอยากดูมากกว่าอ่าน

คำถามที่พบบ่อยเกี่ยวกับการดาวน์โหลดไฟล์ด้วย cURL

จะดาวน์โหลดไฟล์ด้วย cURL และตั้งชื่อเฉพาะได้อย่างไร?

ใช้ -o ตามด้วยชื่อไฟล์ที่ต้องการ: curl -L -o yourname.ext <url> อย่าลืมเพิ่ม -L เพื่อไม่ให้ redirect ทำให้การดาวน์โหลดล้มเหลว

จะ resume การดาวน์โหลด cURL ที่ล้มเหลวได้อย่างไร?

รัน curl -C - -LO <url> วิธีนี้จะใช้ได้ก็ต่อเมื่อเซิร์ฟเวอร์รองรับ range request — ตรวจสอบก่อนด้วย curl -I <url> แล้วมองหา Accept-Ranges: bytes ใน response

cURL ดาวน์โหลดไฟล์ที่ต้องล็อกอินได้ไหม?

ได้ และมี 4 วิธีหลัก: basic auth (-u user:pass), bearer token (-H "Authorization: Bearer <token>"), session แบบ cookie (-b cookies.txt), หรือไฟล์ .netrc สำหรับสภาพแวดล้อมที่ใช้สคริปต์ ดูหัวข้อ authentication ด้านบนสำหรับรายละเอียดครบ ๆ และดูว่าแต่ละแบบเหมาะกับอะไร

ความต่างระหว่าง cURL กับ wget สำหรับดาวน์โหลดไฟล์คืออะไร?

cURL รองรับโปรโตคอลได้มากกว่า และโดยทั่วไปเหมาะกับการเขียนสคริปต์, การ pipe, และการดาวน์โหลดไฟล์เดี่ยวหรือชุดเล็กแบบแม่นยำกว่า ส่วน wget ถูกออกแบบมาสำหรับการ crawl แบบ recursive และ mirror ทั้งไดเรกทอรีของเว็บ จึงเหมาะกว่าสำหรับการดึงไฟล์สแตติกจำนวนมาก

ทำไม cURL ถึงดาวน์โหลดหน้า HTML แทนที่จะเป็นไฟล์จริง?

มีผู้ต้องสงสัยหลักสองราย: คุณลืมใส่ -L แล้วเซิร์ฟเวอร์พาไปยังที่อื่น หรือหน้านั้นต้องใช้ JavaScript เพื่อเรนเดอร์เนื้อหาจริง ซึ่ง curl ทำไม่ได้อยู่แล้ว ในกรณีหลัง คุณจะต้องใช้เครื่องมือที่เรนเดอร์หน้าเว็บได้ แทนที่จะเพิ่ม flags ให้ curl ต่อไป

เรียนรู้เพิ่มเติม

Ke
Ke
CTO ที่ Thunderbit | นักวิทยาศาสตร์ข้อมูลอาวุโสและผู้เชี่ยวชาญด้านแมชชีนเลิร์นนิง ด้วยประสบการณ์เกือบสิบปีในด้านแมชชีนเลิร์นนิงและวิทยาศาสตร์ข้อมูล เคเฉินเป็นศิษย์เก่ามหาวิทยาลัยโคลัมเบีย และอดีตนักวิทยาศาสตร์ข้อมูลอาวุโสที่ Walmart Labs ด้วยความเชี่ยวชาญลึกซึ้งที่ได้รับการยอมรับจากเพื่อนร่วมสายงานใน Python, R, Java และสถิติ เขาจึงแบ่งปันมุมมองที่ผ่านการพิสูจน์มาแล้วในการพัฒนาอัลกอริทึม AI ที่ซับซ้อนจากแนวคิดไปสู่สถาปัตยกรรมระดับใช้งานจริง
Topics
ดาวน์โหลดไฟล์ด้วย cURLระบบอัตโนมัติจากบรรทัดคำสั่งการโอนย้ายไฟล์ที่เชื่อถือได้
สารบัญ
Thunderbit · เอเจนต์ข้อมูลเว็บด้วย AI

ดึงข้อมูลจากทุกหน้าได้ใน คลิกเดียว

ได้รับความไว้วางใจจากผู้ใช้กว่า 250,000+ คน
มีแพ็กเกจใช้ฟรี
จากหน้าเว็บสู่สเปรดชีต
อธิบายสิ่งที่คุณต้องการ — AI Agent ของ Thunderbit จะดึงข้อมูลให้และส่งออกไปยัง Excel, Google Sheets, Airtable หรือ Notion เริ่มใช้ได้ฟรี
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week