Ulasan chromedp: Browser Asli Tetap Butuh Kondisi Kesiapan yang Tepat

Terakhir diperbarui pada August 17, 2026
Ulasan chromedp: Browser Asli Tetap Butuh Kondisi Kesiapan yang Tepat
Ringkasan AI

chromedp adalah library pure-Go berlisensi MIT yang mengendalikan Chrome asli melalui Chrome DevTools Protocol. Library ini membaca DOM setelah JavaScript halaman selesai berjalan langsung dari program Go, tanpa WebDriver atau runtime Node terpisah. Modul Go-nya terkompilasi ke dalam aplikasi, tetapi sistem yang dijalankan tetap memerlukan executable Chrome eksternal yang masa hidupnya diatur lewat context Go. Instalasinya cukup dengan satu go get plus Chrome yang harus disediakan sendiri: buat allocator, turunkan context, lalu jalankan daftar aksi.

chromedp adalah library pure-Go berlisensi MIT yang mengendalikan Chrome asli lewat Chrome DevTools Protocol. Library ini membaca DOM setelah JavaScript halaman selesai jalan, langsung dari program Go, tanpa perlu WebDriver terpisah atau runtime Node. Modul Go-nya memang terkompilasi ke dalam aplikasi, tapi sistem yang dijalankan tetap butuh executable Chrome eksternal, dan masa hidupnya diatur lewat context Go.

Instalnya cukup dengan satu go get plus Chrome yang harus saya sediakan sendiri: buat allocator, turunkan context, lalu berikan daftar aksi ke Run. Di host macOS arm64 ini, dengan headless shell yang sudah hangat di disk, proses baru sampai hasil script pertama punya median 102 ms. Ini cuma baseline lokal, bukan klaim umum bahwa startup tidak pernah jadi bottleneck. Pada fixture yang menyuntikkan sebuah link 800 milidetik setelah load, dua dari empat strategi baca kembali sebelum link-nya ada.

Browser-nya nyata, kontennya ada, dan kodenya memang belum menunggu dengan benar. Celah itulah hal paling berguna yang saya pelajari dari chromedp, dan ini bukan bug — ini soal bedanya antara "saya sudah merender halaman" dan "saya sudah menunggu hal yang memang saya butuhkan," pembedaan yang sering disederhanakan habis-habisan dalam cerita soal browser headless. Strategi menunggu, bukan browser-nya, yang menentukan apakah Anda dapat datanya. Semua angka di sini berasal dari fixture lokal yang saya kendalikan, dengan ground truth yang dicatat sebelum run apa pun, dan ringkasan mentahnya ada di folder chromedp di repo benchmark kami.

Apa sebenarnya chromedp

Stack chromedp dibuat ringkas sejak awal. Tidak ada Selenium server. Tidak ada shim WebDriver. Tidak ada runtime Node di balik layar. Program Go Anda membuka WebSocket ke instance Chrome dan ngobrol langsung lewat CDP, yang secara garis besar adalah protokol wire yang sama seperti yang dipakai Puppeteer, hanya tanpa JavaScript.

Repo ini punya 13.212 bintang dan 178 isu terbuka saat saya cek pada 27 Juli 2026, dengan lisensi MIT. Versi yang saya uji adalah v0.16.0, yaitu tag terbaru di repo. Perlu dicatat supaya tidak bikin bingung: halaman Releases di GitHub masih menampilkan v0.15.1 (dirilis 2026-04-01) sebagai objek rilis terbaru, sementara go get github.com/chromedp/chromedp@latest mengarah ke v0.16.0. Modul Go dan objek rilis GitHub memang sudah agak bergeser di sini. Bukan rusak, cuma agak nyebelin saat Anda mencoba memastikan apa yang sebenarnya sedang dijalankan.

Model mentalnya adalah context Go dari ujung ke ujung. Anda membuat allocator context (yang tahu cara memulai Chrome), menurunkan browser context darinya, lalu memanggil chromedp.Run(ctx, actions...) dengan daftar Action. Child context dari browser context adalah tab baru. Batalkan context, maka objek yang diwakilinya ikut hilang. Kalau Anda sudah pernah kerja dengan concurrency di Go, ini terasa sangat familiar; kalau belum, panduan kami untuk mulai web scraping di Go adalah pintu masuk yang jauh lebih ramah daripada godoc chromedp.

Satu batasan penting dari awal: chromedp memberi Anda DOM yang sudah dirender. Ia tidak memberi Anda data terstruktur. Apa pun yang Anda ambil dari DOM itu — field, tabel, harga — adalah kode yang harus Anda tulis dan rawat sendiri. Ini driver, bukan framework scraper.

Mesin di balik layar

Di chromedp, semuanya adalah Action, dan Run mengeksekusi potongan Action itu berurutan terhadap sebuah target. Navigate, Click, Evaluate, OuterHTML, WaitVisible — semuanya memakai interface yang sama, semuanya bisa dirangkai, semuanya cuma perintah CDP yang dibungkus tipe Go. Keseragaman ini adalah keputusan desain terbaik library ini, karena membuat lapisan praktis dan protokol mentah berada di level yang sama.

Ini penting, karena lapisan praktisnya memang sengaja tipis. chromedp dibangun di atas cdproto, yaitu kumpulan binding Go bertipe yang dihasilkan untuk mencakup seluruh permukaan DevTools Protocol, dan godoc chromedp mendokumentasikan kedua lapisan itu berdampingan. Kalau action praktis yang Anda butuhkan belum ada, Anda tinggal turun ke panggilan domain — network.Enable(), page.CaptureScreenshot(), runtime.Evaluate() — di dalam Run yang sama. Tidak ada tembok antara "API yang nyaman" dan "API asli", dan itu tidak selalu berlaku untuk browser driver lain.

Action untuk menunggu adalah tempat keputusan harian dibuat, dan jumlahnya lebih banyak daripada yang dipakai kebanyakan orang:

Action menungguYang diblok sampai
WaitReady(sel)node terpasang di DOM
WaitVisible(sel)node benar-benar terlihat
WaitNotPresent(sel) / WaitNotVisible(sel)kebalikannya, berguna untuk spinner
Poll(js, res)mengevaluasi predikat JavaScript secara berkala sampai bernilai true

Manajemen proses adalah bagian mesin lain yang layak dipahami, karena menentukan apakah program Anda ninggalin browser yang masih hidup di belakang. chromedp memulai Chrome lewat exec.CommandContext milik Go. Membatalkan context itu akan mematikan prosesnya. Detail implementasi tunggal ini menjelaskan perilaku yang bagus sekaligus sisi tajam yang saya temui saat pengujian.

Setup-nya adalah binary Go plus Chrome yang harus Anda sediakan

go get github.com/chromedp/chromedp berjalan mulus ke v0.16.0 tanpa drama, dan dependency tree-nya tidak berisi import cgo. Jadi klaim "pure Go, tanpa dependensi eksternal" yang sering Anda lihat itu benar — untuk modul Go-nya.

Namun, itu tidak berlaku untuk runtime. chromedp mengendalikan Chrome eksternal, dan tanpa Chrome di mesin, run langsung gagal. Semua pengukuran yang saya ambil menyediakan executable yang tepat lewat chromedp.ExecPath, diarahkan ke Chrome for Testing headless shell 151.0.7922.10. Ini bukan kritik — browser memang butuh browser — tetapi "tanpa dependensi eksternal" dan "Anda harus menyertakan Chrome 155 MB bersama binary Anda" adalah dua cerita deployment yang sangat berbeda, dan cuma salah satunya yang muncul di README.

Ada landmine setup kedua yang menghabiskan waktu saya dan layak diketahui sebelum Anda menulis kode apa pun. Isu chromedp #1591 melaporkan runner go test di Go 1.25+ membatalkan NewExecAllocator di tengah start; kode yang sama berjalan baik sebagai binary terkompilasi. Saya membangun binary probe dengan go build dan menjalankannya untuk setiap pengukuran, alih-alih lewat go test. Go yang dipakai di sini 1.26.5, macOS arm64. Kalau pengalaman pertama Anda dengan chromedp adalah file test yang mati saat Chrome baru mulai, baca isu itu dulu sebelum menyalahkan kode Anda sendiri.

Praktik langsung: empat cara membaca halaman yang sama, dua di antaranya kosong

Bagan hasil terukur: Strategi baca mana yang melihat setiap link?

Fixture-nya adalah server lokal di 127.0.0.1 yang menyajikan tiga kelas konten yang cuma beda di kapan mereka masuk ke DOM: sebuah <a> statis di byte yang disajikan, sebuah <a> yang dibuat oleh <script> inline selama parse awal, dan sebuah <a> yang dibuat oleh setTimeout beberapa milidetik yang bisa dikonfigurasi setelah event load. Marker dan href untuk dua link yang dibuat script dirangkai dari potongan string di JavaScript, jadi tidak ada literal yang utuh di byte yang disajikan. Jadi, status "found" membuktikan Chrome menjalankan JavaScript, bukan sekadar membaca HTML.

Recall dihitung di Python terhadap marker ground-truth yang sudah didaftarkan sebelumnya, bukan di dalam probe Go, jadi probe tidak bisa curang dengan tahu jawabannya. Setiap strategi dijalankan tiga kali; himpunan yang ditemukan identik di ketiga percobaan.

Strategi bacaLink HTML statisDisuntik saat parseDisuntik 800 ms setelah loadWaktu
Navigate + baca, tanpa menungguditemukanditemukantidak ditemukan317 ms
WaitReady("body")ditemukanditemukantidak ditemukan107 ms
WaitVisible("#delayed-injected")ditemukanditemukanditemukan912 ms
Poll sampai marker munculditemukanditemukanditemukan972 ms

Dua baris kembali dengan dua link dari tiga. Pembacaan naif gagal karena Navigate selesai saat event load terjadi, sementara link ketiga belum ada. WaitReady("body") gagal karena alasan yang lebih halus dan lebih berbahaya dalam praktik: body sudah terpasang saat load, jadi wait langsung terpenuhi dan Anda merasa sudah melakukan hal yang benar. Ia selesai dalam 107 ms, lebih cepat daripada jalur tanpa wait, dan memberi Anda halaman yang sama-sama belum lengkap.

Untuk memastikan mekanismenya, bukan sekadar menebak, saya menyapu delay injeksi dan menjalankan ulang dua ekstrem (recall-summary.json):

Delay injeksi setelah loadPembacaan tanpa wait melihatnyaWaitVisible melihatnyaElapsed WaitVisible
0 msya (race)ya109 ms
100 mstidakya208 ms
400 mstidakya519 ms
800 mstidakya911 ms
1500 mstidakya1625 ms

Elapsed WaitVisible mengikuti delay injeksi pada fixture ini — 100 ke 208, 400 ke 519, 800 ke 911, 1500 ke 1625 — bukti bahwa ia benar-benar menunggu node muncul, bukan membaca terlalu cepat. Baris 0 ms adalah batasnya: setTimeout(…, 0) bisa saja terpanggil sebelum pembacaan langsung, jadi jalur tanpa wait dapat menangkapnya. Pada 100 ms dan di atasnya dalam penyapuan ini, jalur tanpa wait gagal menangkapnya di setiap run.

Di produksi, kesalahan timing yang sama bisa menghasilkan HTML yang valid tapi tanpa baris hasil yang diekstrak, lalu proses keluar 0 kalau pipeline tidak memeriksa cardinality output. Itu mode kegagalan yang masuk akal dan didukung oleh perilaku fixture, meski bukan insiden yang diukur di sini. Rendering hanyalah separuh syarat; pembacaan harus menunggu kondisi level aplikasi yang terhubung ke data yang Anda inginkan.

WaitReady dan WaitVisible bukan peringkat — mereka menjawab pertanyaan berbeda

Frasa yang umum adalah WaitVisible itu "lebih andal" daripada WaitReady. Itu terlalu tidak presisi dan bisa berbahaya. Pada halaman dengan node yang terpasang di DOM tapi dibuat display: none, keduanya akan berpisah dengan jelas (waitsem-summary.json, tiga run identik):

Node targetActionHasilWaktu
terpasang, display:noneWaitReadykembali~6 ms
terpasang, display:noneWaitVisibletimeout, context deadline exceeded4000 ms
node terlihatWaitVisible, query defaultkembali4–12 ms
node terlihatWaitVisible, ByIDkembali1–2 ms
node terlihatWaitVisible, ByQuerykembali1 ms

WaitReady berarti terpasang. WaitVisible berarti terlihat. Kalau Anda bertanya yang salah, Anda bisa melangkah melewati konten yang tidak pernah tampil, atau malah kejebak selama timeout penuh pada node yang memang tidak akan pernah terlihat. Perilaku deadline-nya sendiri bersih — context deadline exceeded yang tepat di 4 s, tanpa hang, tanpa zombie state — lebih baik daripada yang dikelola beberapa driver lain.

Satu jebakan yang dilaporkan tidak muncul. Isu #440 melaporkan WaitVisible("#id") macet dengan query default, dan hal itu tidak ter-reproduksi di v0.16.0 — query default, ByID, dan ByQuery semuanya kembali pada node yang terlihat di setiap run. Tidak ter-reproduksi bukan berarti sudah diperbaiki: ini cuma satu bentuk selector di satu halaman, jadi belum menutup isu tersebut.

defer cancel() yang Anda lewati sedang menyangga atap

Yang dihitung adalah proses, bukan nilai return. Setiap run lifecycle memakai --user-data-dir unik dan menghitung proses browser Chrome yang nyata dengan pgrep, sambil memfilter child renderer. Setiap jalur dijalankan tiga kali (lifecycle-summary.json).

Jalur keluar (macOS, masing-masing 3 run)Apa yang terjadi pada chrome-headless-shell yang diluncurkanWaktu
Batalkan context dan allocatorhilang13, 13, dan 12 milidetik
Keluar dari proses Go tanpa membatalkanbertahan di luar program Anda — nol proses browser sebelum, satu sesudah probe keluar; jadi orphan di tiga dari tiga run—

Membatalkan itu bersih, cepat, persis seperti yang dijanjikan exec.CommandContext. (Semua orphan lalu di-force-kill oleh harness; host dibersihkan sampai tuntas.)

Ini perilaku yang sudah diketahui, terdokumentasi, dan terikat platform — pengukurannya milik saya, penemuannya bukan. Tracker chromedp sudah membahasnya dari beberapa sisi: #774 menjelaskan non-exit yang sama di FreeBSD, #752 melaporkan proses Chromium yang hang di macOS, dan #562 plus #1566 menjabarkan mekanismenya. Yang saya tambahkan adalah hitungan proses dan timing di kedua sisi perbandingan, yang tidak disediakan oleh laporan kualitatif itu.

Mekanismenya sendiri berkaitan dengan build tag yang penting dipahami. Di source v0.16.0, allocate_linux.go menetapkan Pdeathsig = SIGKILL pada child process, jadi Linux mendapat sinyal parent-death di level kernel. allocate_other.go, yang dikompilasi di macOS, menjadikan panggilan itu no-op. Tidak ada sinyal yang setara di darwin, jadi tidak ada yang membunuh Chrome saat program Anda keluar. Sementara itu, penjelasan godoc terdengar seperti janji umum — command default "mengirim SIGKILL ke browser yang masih terbuka saat program Go keluar" — padahal batasan Linux hanya hidup di source bertag build yang harus Anda baca langsung. Menyebut dokumentasinya terlalu menjanjikan itu adil; menyebutnya bug chromedp tidak.

Konsekuensi praktisnya tetap sama: di macOS, defer cancel() adalah bagian yang menahan beban. Lewati itu dan setiap run akan meninggalkan browser process. Saya tidak menguji Linux, jadi saya tidak menggeneralisasi hasil orphan ke sana — source memang mengisyaratkan Linux berbeda, dan itu bukan pengukuran.

Cold start, concurrency, dan hal membosankan yang menentukan deployment Anda

Bagan hasil terukur: Cold start dan dua bentuk concurrency

102 ms adalah median dari proses baru, allocator, context, navigasi localhost, dan Evaluate pertama di lima proses, dengan rentang 98 hingga 111 ms (coldstart-summary.json). Pada fixture macOS arm64 ini dengan headless shell di disk yang sudah hangat, startup jauh lebih kecil dibanding tunggu konten tertunda. Container, filesystem dingin, CI, lingkungan serverless, dan navigasi produksi tidak diukur.

Untuk concurrency, chromedp memberi Anda dua bentuk — satu browser dengan beberapa child context (tab), atau beberapa browser independen. Empat navigasi, masing-masing tiga run (concurrency-summary.json):

ModeWaktu total (p50)RentangPuncak proses browser Chrome
Satu browser bersama, 4 child context214 ms209–2191
4 browser terpisah264 ms261–2784

Temuan terukur yang utama adalah jumlah proses: satu proses browser Chrome versus empat untuk empat navigasi lokal trivial ini. Rentang wall-time tidak saling tumpang tindih, tapi tetap lebih tepat dibaca sebagai arah, bukan benchmark throughput. RSS dan PSS tidak diukur, jadi tes ini tidak membuktikan penghematan memori.

Probe error-path kecil di sini tidak cukup rinci untuk mendukung klaim ketahanan: draft ini tidak mengidentifikasi apakah status HTTP, error navigasi, event, atau logika harness yang memunculkan masing-masing kondisi. Perlakukan penanganan 500/dead-link sebagai belum dilaporkan sampai hasil API yang tepat dan artifact mentahnya dipublikasikan.

Yang belum diuji, dan karena itu di luar cakupan angka-angka ini: perilaku lifecycle di Linux, concurrency di atas N=4 atau dengan kerja nyata per halaman, delta memori (saya menghitung proses, bukan RSS), interception network dan capture request, serta laporan timeout WaitReady yang masih terbuka di #168 dan #1593 — itu menggambarkan timeout intermiten, sedangkan yang saya ukur adalah semantik wait, pertanyaan yang berbeda. Satu mesin, satu build Chrome.

chromedp bukan satu-satunya driver Go CDP di bench ini: rod diuji pada fixture, harness, host, dan build Chrome yang identik pada sesi yang sama, dan akan dapat tulisannya sendiri.

Kelebihan dan kekurangan

Kelebihan:

  • Akses CDP asli — action praktis dan panggilan domain mentah cdproto bisa dirangkai dalam Run yang sama, jadi Anda tidak mentok di batas API.
  • Baseline cold-cycle lokal 102 ms p50 dengan sebaran 98–111 ms pada fixture macOS yang diuji.
  • Cancel membersihkan Chrome dalam sekitar 13 ms, konsisten, di setiap run.
  • Child context berbagi satu proses browser untuk N tab (1 proses versus 4 untuk browser terpisah).
  • Deterministik dalam pengujian — set recall, semantik wait, dan hasil lifecycle identik di tiga pengulangan masing-masing.
  • Penanganan deadline bersih: WaitVisible pada kondisi yang tak terjangkau kembali sebagai context deadline exceeded yang tepat pada 4 s, bukan hang.
  • Modul pure-Go (tanpa cgo), berlisensi MIT; namun executable Chrome eksternal tetap diperlukan saat runtime.

Kekurangan:

  • Memerlukan Chrome eksternal saat runtime; reputasi "tanpa dependensi" cuma berlaku untuk modul Go-nya.
  • WaitReady("body") adalah jebakan yang terasa benar tapi diam-diam melewatkan konten pasca-load — ia kembali dalam 107 ms dengan halaman yang belum lengkap.
  • Jalur naif Navigate + baca akan melewatkan apa pun yang disuntikkan ≥ ~100 ms setelah load, secara deterministik, tanpa error.
  • Di macOS, keluar tanpa cancel() membuat browser jadi orphan (3/3 run). Ini sudah diketahui dan terikat platform, tapi mudah sekali kelupaan.
  • Kalimat godoc tentang SIGKILL saat exit terdengar universal, padahal mekanismenya cuma ada di source bertag build Linux.
  • go test di Go 1.25+ bisa membatalkan startup allocator (#1591); bangun binary sebagai gantinya.
  • Ia mengembalikan DOM, bukan data terstruktur — setiap field yang Anda mau adalah kode parsing yang harus Anda miliki dan rawat.
  • Tag terbaru (v0.16.0) lebih maju daripada objek GitHub Release terbaru (v0.15.1), yang bikin cek versi sebentar jadi membingungkan.

Untuk siapa chromedp cocok, dan siapa yang sebaiknya menghindarinya

Kalau service Anda sudah pakai Go dan Anda butuh browser asli di dalamnya, chromedp sangat dekat dengan pilihan yang paling masuk akal. Tidak ada proses Node yang harus diawasi, tidak ada server WebDriver yang harus tetap hidup, satu binary terkompilasi plus Chrome yang Anda kirim atau install. Model context-nya langsung nyambung dengan primitif concurrency Go, jadi masa hidup browser akhirnya diatur oleh disiplin defer yang sama seperti bagian lain dari codebase Anda. Dan kalau Anda butuh sesuatu yang tidak dicakup API praktis — event network CDP, hook lifecycle halaman yang presisi, trik level protokol — Anda bisa turun ke cdproto tanpa keluar dari library.

Ini juga cocok kalau Anda ingin kontrol eksplisit atas proses waiting. Action wait adalah primitive, bukan heuristik; mereka melakukan persis apa yang mereka bilang, dan itu jadi fitur setelah Anda menerima bahwa memilih dengan benar sekarang adalah tugas Anda.

Hindari kalau tim Anda tidak menulis Go — komitmen ke bahasa adalah biaya nyata, bukan library-nya. Hindari kalau Anda ingin ergonomi auto-wait yang menebak dengan benar atas nama Anda, karena chromedp tidak akan menebak; ia akan melakukan persis yang Anda minta dan mengembalikan apa pun yang dimiliki halaman pada saat itu. Hindari, atau siapkan anggaran serius, kalau yang Anda butuhkan sebenarnya adalah record terstruktur, bukan DOM: setiap field adalah selector yang harus Anda tulis, uji, dan perbaiki ketika situs berubah. Dan kalau kebutuhan Anda cuma "ambilkan data dari 500 URL ini", menyiapkan orkestrasi browser di Go adalah mesin yang cukup berat untuk permintaan itu. Panduan otomatisasi browser kami membahas kapan mesin seperti ini layak dipakai dan kapan tidak.

Alternatif, termasuk di mana stack kami sendiri cocok

Di kategori browser driver, rod adalah driver Go CDP lain, sementara Playwright dan Puppeteer adalah opsi sisi Node yang dibahas dalam perbandingan Playwright vs Puppeteer kami. Kontrak waiting mereka tidak bisa dipertukarkan. Playwright melakukan auto-wait untuk actionability sebelum banyak action; itu pun belum memberi tahu kapan data aplikasi benar-benar selesai tiba setelah action dilakukan. chromedp memberi Anda primitive wait level rendah dan menyerahkan baik actionability maupun kondisi kesiapan level aplikasi kepada caller. Kalau Anda sedang memetakan lanskap yang lebih luas, ringkasan scraper open-source yang kami uji mencakup crawler statis dan library ekstraksi di sisi lain garis ini.

Ulasan terkait: Ulasan Browserless.

Layanan ekstraksi terkelola adalah kategori yang berbeda. Ia menukar kontrol browser dan selector dengan rendering dan pembentukan skema yang di-outsourcing. Itu bisa berguna saat deliverable-nya adalah record terstruktur, sedangkan chromedp lebih cocok saat browser harus tetap berada di bawah kontrol service Go Anda. Kami membangun Thunderbit, salah satu layanan seperti itu, tapi tidak menjalankannya melawan fixture ini; jadi tes ini tidak mendukung perbandingan kesetaraan, latensi, kualitas ekstraksi, atau biaya dengan chromedp.

Coba Thunderbit untuk Ekstraksi Data Web

Putusan

Haruskah Anda memakai chromedp? Ya, kalau Anda menulis Go dan ingin browser asli yang berada di bawah kendali Anda. Pada fixture lokal ini, library ini mencapai hasil script pertama dalam median 102 ms, membersihkan Chrome dalam sekitar 13 ms setelah cancel, dan memakai satu proses browser untuk empat tab concurrent. Itu semua observasi terbatas, bukan janji performa universal; daya tarik yang tahan lama adalah akses CDP langsung dari Go ketika lapisan praktisnya sudah tidak cukup.

Tetap ukur klaimnya dengan benar, karena reputasinya melebihkan dua hal. "Pure Go, tanpa dependensi" menggambarkan modulnya; saat runtime Anda tetap harus mengirim dan mengelola binary Chrome. Dan "pakai browser headless lalu Anda akan dapat konten dinamis" cuma benar kalau wait Anda diarahkan ke node yang Anda mau — pembacaan naif dan WaitReady("body") sama-sama memberi saya halaman yang kehilangan konten yang disuntikkan 800 ms setelah load, diam-diam, setiap kali. Di macOS, defer cancel() bukan soal gaya; kalau Anda melewatkannya, satu browser bocor per run, yang merupakan perilaku platform yang sudah diketahui tapi tetap jadi masalah Anda untuk ditangani. Kalau tiga hal itu benar, chromedp adalah salah satu browser driver yang paling bisa diprediksi yang pernah saya ukur. Kalau salah, ia gagal diam-diam, dan itu cara terburuk bagi scraper untuk gagal.

Coba Thunderbit untuk Ekstraksi Data Web Get Started Free

FAQ

Apakah chromedp benar-benar bisa melihat konten yang dirender JavaScript?
Ya — tapi hanya dengan wait yang diarahkan ke node yang Anda butuhkan. Pada fixture di mana sebuah link disuntikkan 800 ms setelah event load, Navigate plus pembacaan melewatkannya dan WaitReady("body") juga melewatkannya, sementara WaitVisible pada node itu dan poll JavaScript sama-sama berhasil mengambilnya, masing-masing dalam tiga dari tiga run. Saat delay disapu, pembacaan tanpa wait melewatkan node pada semua setelan mulai 100 ms ke atas. Rendering itu perlu; menunggu dengan benar itulah yang membuatnya cukup.

Apa bedanya WaitReady dan WaitVisible?
WaitReady menunggu sampai node terpasang di DOM. WaitVisible menunggu sampai node benar-benar terlihat. Pada node yang terpasang tapi bergaya display: none, WaitReady kembali dalam sekitar 6 ms sedangkan WaitVisible menunggu sampai deadline context 4 detik dan kembali dengan context deadline exceeded yang bersih. Keduanya bukan yang "lebih andal" — mereka menjawab pertanyaan berbeda, dan memilih yang salah adalah jebakan sebenarnya.

Apakah saya benar-benar perlu defer cancel() dengan chromedp?
Di macOS, ya. Membatalkan context dan allocator membersihkan Chrome yang diluncurkan dalam 12–13 ms di setiap run; keluar dari proses Go tanpa membatalkan meninggalkan browser orphan di ketiga run. Ini perilaku yang sudah diketahui dan terikat platform — tracker chromedp mendokumentasikan pola non-exit yang sama di sistem non-Linux lain, dan kill berbasis parent-death yang menanganinya ada di source bertag build khusus Linux. Saya tidak menguji Linux, jadi perlakukan hasil orphan sebagai khusus macOS.

Apakah chromedp perlu Chrome yang dipasang terpisah?
Ya. Modul Go-nya sendiri pure Go tanpa cgo, tapi ia mengendalikan browser eksternal dan langsung gagal tanpa itu. Saya secara eksplisit menyediakan headless shell Chrome for Testing 151.0.7922.10 lewat chromedp.ExecPath. Keuntungannya adalah biaya startup kecil: satu cold cycle penuh sampai hasil script pertama punya median 102 ms di lima proses baru, dengan rentang 98–111 ms.

Sebaiknya satu browser dibagi ke banyak tab atau tiap tab pakai browser terpisah?
Pilih child context kalau tujuan Anda meminimalkan jumlah proses browser. Empat navigasi localhost lewat satu browser memakai 1 proses browser Chrome; empat browser terpisah memakai 4. Waktu total juga lebih baik pada setup bersama (median 214 ms versus 264 ms), tapi empat halaman lokal trivial bukan benchmark throughput. Memori tidak diukur. Browser terpisah tetap bisa jadi pilihan yang tepat kalau Anda butuh isolasi sesi yang lebih kuat, proxy yang berbeda, atau radius crash yang lebih kecil; trade-off itu di luar tes ini.

Ke
Ke
CTO di Thunderbit | Senior Data Scientist & Expert ML Dengan pengalaman hampir satu dekade di bidang machine learning dan data science, Ke Shen adalah lulusan Columbia University dan mantan Senior Data Scientist di Walmart Labs. Dengan keahlian mendalam yang diakui sejawat dalam Python, R, Java, dan Statistik, ia membagikan wawasan teruji lapangan tentang bagaimana membawa algoritma AI yang kompleks dari teori ke arsitektur siap produksi.
Topics
Web Scraping ToolsAI Web Scraper
Daftar isi
Thunderbit · Agen data web AI

Ekstrak data dari halaman apa pun dalam 1 klik

Dipercaya 250.000+ pengguna
tersedia paket gratis
Dari halaman web ke spreadsheet
Jelaskan kebutuhanmu — Agen AI Thunderbit akan men-scrape lalu mengekspor ke Excel, Google Sheets, Airtable, atau Notion. Gratis untuk memulai.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week