Geonode logo
Geonode Team

Geonode Team

Diperbarui: 7 Oktober 2026

Diterbitkan: 2 September 2026

Cara Mengambil Tangkapan Layar dengan Playwright

`await page.screenshot({ path: 'shot.png' })` mengambil tangkapan layar. Itu bagian yang mudah, dan di situlah kebanyakan panduan berhenti. Bagian yang lebih sulit adalah membuat tangkapan layar yang persis sama dua kali — hal ini sangat penting jika Anda membandingkannya, dan sama sekali tidak penting jika Anda hanya melihat satu tangkapan layar. Panduan ini membahas keduanya, ditambah opsi-opsi yang mengontrol apa yang akan ditangkap, serta situasi di mana tangkapan layar benar-benar merupakan alat verifikasi yang tepat.

Kami ingin menjelaskan kepentingan kami: kami adalah Geonode dan kami menjual layanan proxy; tangkapan layar melalui proxy merupakan salah satu contoh penggunaan yang paling praktis untuk produk kami — memverifikasi tampilan sebenarnya suatu halaman dari negara lain adalah hal yang tidak dapat diungkapkan oleh API mana pun. Peringatan jujurnya adalah biayanya: browser akan memuat setiap gambar, font, skrip, dan pramuat video, sehingga mengambil tangkapan layar adalah aktivitas yang paling boros bandwidth yang dapat Anda lakukan pada koneksi dengan kuota terbatas. Ada bagian di bawah ini tentang cara menguranginya, dan teknik yang dijelaskan di sana akan menghemat lebih banyak uang daripada jika Anda memilih penyedia yang lebih murah.

Tiga Jenis Tangkapan Layar

Viewport — apa yang saat ini terlihat, pengaturan default:

await page.screenshot({ path: 'viewport.png' });

Halaman Penuh — dokumentasi menjelaskannya sebagai "tangkapan layar dari halaman yang dapat digulir sepenuhnya, seolah-olah Anda memiliki layar yang sangat tinggi dan halaman tersebut dapat muat sepenuhnya di dalamnya":

await page.screenshot({ path: 'full.png', fullPage: true });

Elemen — "Terkadang berguna untuk mengambil tangkapan layar dari satu elemen saja":

await page.getByRole('article').screenshot({ path: 'element.png' });

Memilih di antara ketiganya sebagian besar bergantung pada apa yang akan Anda lakukan dengan hasilnya. Tangkapan layar viewport menjawab "apa yang dilihat pengguna pertama kali". Tangkapan layar halaman penuh menjawab "apa yang ada di halaman ini". Tangkapan layar elemen menjawab "apakah komponen ini terlihat benar", dan ini adalah yang paling konsisten di antara ketiganya untuk perbandingan karena mengesampingkan segala hal yang tidak Anda tanyakan.

Tangkapan Layar Seluruh Halaman dan Masalah yang Muncul

fullPage: true adalah opsi yang paling sering dipilih orang, namun juga yang memiliki paling banyak keterbatasan.

Konten yang dimuat secara lazy-load mungkin belum muncul. Playwright akan menggulir untuk menangkap layar, tetapi gambar dan komponen yang dimuat saat kursor melewati area tertentu mungkin belum selesai dimuat saat proses penangkapan selesai. Solusi yang dapat diandalkan adalah menggulir secara sengaja dan menunggu hingga konten yang Anda harapkan muncul:

await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
await expect(page.getByRole('img').last()).toBeVisible();
await page.evaluate(() => window.scrollTo(0, 0));
await page.screenshot({ path: 'full.png', fullPage: true });

Header yang menempel (sticky) terulang atau mengambang secara aneh. Elemen dengan properti position: fixed atau sticky berperilaku tidak terduga dalam tangkapan yang disambung. Opsi style — "string CSS yang disisipkan ke halaman untuk penataan gaya selama proses penangkapan" — adalah solusi yang tepat:

await page.screenshot({
  path: 'full.png',
  fullPage: true,
  style: '.sticky-header { position: absolute !important; }',
});

Halaman yang sangat panjang menghasilkan file yang sangat besar. Feed dengan gulir tak terbatas tidak memiliki bagian bawah yang jelas. Pertimbangkan clip untuk menangkap area yang ditentukan, yang menerima "objek yang menentukan pemotongan gambar hasil tangkapan".

Overlay juga ditangkap. Banner cookie, widget obrolan, dan modal muncul dalam tangkapan layar persis seperti yang terlihat oleh pengguna. Jika Anda tidak menginginkannya, tutup terlebih dahulu — dan jika tidak bisa, mask adalah alat yang tepat.

Tangkapan Layar dan Buffer Elemen

Tangkapan layar elemen akan menggulirkan elemen tersebut ke dalam tampilan dan hanya menangkap kotak pembatasnya, sehingga menjadikannya pilihan default yang tepat untuk pemeriksaan tingkat komponen.

const card = page.getByTestId('product-card').first();
await card.screenshot({ path: 'card.png' });

Ada dua hal yang tidak dapat dilakukan oleh tangkapan layar ini: menangkap konten yang terpotong oleh overflow: hidden

, dan menangkap apa pun di luar kotak elemen tersebut meskipun secara visual tumpang tindih.

Buffer, bukan berkas. Dokumentasi menyebutkan bahwa "daripada menulis ke berkas, Anda dapat memperoleh buffer berisi gambar tersebut dan memprosesnya lebih lanjut atau meneruskannya ke fasilitas perbandingan piksel pihak ketiga". Hapus ``path`

` dan Anda akan mendapatkan byte-nya kembali:

const buffer = await page.screenshot();
const base64 = buffer.toString('base64');

Ini adalah format yang Anda inginkan setiap kali tangkapan layar akan dikirim ke tempat lain selain disk lokal — penyimpanan objek, API, laporan, atau layanan perbandingan. Hal ini juga sepenuhnya menghindari sistem berkas, yang penting dalam runner berbasis kontainer di mana disk bersifat sementara.

Opsi yang Membuat Tangkapan Layar Dapat Direproduksi

Jika Anda membandingkan beberapa tangkapan layar, opsi-opsi ini tidak boleh diabaikan. Jika Anda hanya melihat sekilas salah satunya, abaikan saja.

OpsiNilaiFungsinya
animations

| disabled

, allow

| "Jika disetel ke 'disabled', menghentikan animasi CSS selama pengambilan tangkapan layar" | | caret

| hide

, initial

| "Jika disetel ke 'hide', menyembunyikan kursor teks selama pengambilan tangkapan layar" | | mask

| Locator[]

| "Menentukan elemen yang harus disembunyikan saat mengambil tangkapan layar" | | maskColor

| Warna CSS, default #F0F

| "Tentukan warna yang akan digunakan untuk area yang disembunyikan" | | scale

| css

, device

| "Skala tampilan halaman web" | | omitBackground

| boolean, default false

| "Menyembunyikan latar belakang putih default dan memungkinkan pengambilan tangkapan layar transparan" | | type

| png

, jpeg

, default png

| "Menentukan format file tangkapan layar" | | quality

| 0–100 | "Kualitas gambar untuk format JPEG" — hanya JPEG | | style

| String CSS | Disisipkan ke dalam halaman selama proses penangkapan |

Empat opsi yang mengatasi sebagian besar masalah reproduktibilitas:

**animations: 'disabled'

** menghilangkan sumber perbedaan terbesar antara dua tangkapan layar dari halaman yang sama. Setiap transisi CSS yang sedang berlangsung akan menghasilkan hasil piksel yang berbeda pada setiap eksekusi.

**mask

** mengganti area tertentu dengan warna solid, yang merupakan cara untuk mengesampingkan konten yang benar-benar bervariasi — cap waktu, pengenal sesi, rekomendasi yang dipersonalisasi, iklan — tanpa sepenuhnya mengabaikan perbandingan:

await page.screenshot({
  path: 'page.png',
  mask: [page.getByTestId('timestamp'), page.locator('.ad-slot')],
  maskColor: '#000000',
});

**scale: 'css'

** melakukan penangkapan pada dimensi piksel CSS alih-alih rasio piksel perangkat, sehingga mesin dengan DPI tinggi dan pelaksana CI menghasilkan gambar dengan ukuran yang sebanding. Tetapkan secara eksplisit daripada mengandalkan pengaturan default, karena ini adalah opsi yang paling mungkin berbeda antara laptop Anda dan server build.

**caret: 'hide'

** menghilangkan kursor teks yang berkedip, yang biasanya muncul pada sekitar setengah tangkapan layar halaman apa pun yang memiliki input yang difokuskan.

Tiga hal lain yang perlu diperhatikan untuk memastikan reproduktibilitas, yang tidak ada satupun di antaranya merupakan opsi tangkapan layar: tetapkan ukuran viewport dalam konfigurasi Anda, tetapkan locale dan zona waktu, serta tetapkan font — ketersediaan font berbeda antara mesin pengembang dan kontainer, dan font yang berbeda berarti tata letak yang berbeda.

Tangkapan Layar Otomatis Saat Pengujian Gagal

Konfigurasi tangkapan layar paling berguna di Playwright, dan hanya membutuhkan satu baris kode:

export default defineConfig({
  use: {
    screenshot: 'only-on-failure',
    trace: 'retain-on-failure',
    video: 'retain-on-failure',
  },
});

screenshot: 'only-on-failure' menangkap halaman pada saat pengujian gagal dan melampirkannya ke laporan. Opsi lainnya adalah off , on , dan only-on-failure ; on menangkap tangkapan layar untuk setiap pengujian dan menghasilkan banyak artefak.

Menggabungkannya dengan trace adalah hal yang patut ditekankan, karena jejak (trace) mencakup snapshot DOM, aktivitas jaringan, dan setiap tindakan beserta waktunya. Tangkapan layar hanya menunjukkan bahwa halaman terlihat salah; jejak menjelaskan alasannya. Untuk apa pun yang berjalan tanpa pengawasan, keduanya harus diaktifkan.

Konfigurasi ini juga merupakan cara tercepat untuk mendiagnosis kategori kegagalan yang membingungkan, di mana halaman berhasil ditampilkan — hanya saja bukan halaman yang Anda harapkan. Halaman tantangan, pengalihan login, atau varian regional semuanya menghasilkan waktu tunggu yang tampak seperti masalah elemen hingga Anda melihat tangkapan layar.

Perbandingan Visual dengan toHaveScreenshot

Untuk pengujian regresi visual yang sesungguhnya, bukan sekadar tangkapan layar ad hoc:

await expect(page).toHaveScreenshot('homepage.png');
await expect(page.getByRole('navigation')).toHaveScreenshot('nav.png');

Pada eksekusi pertama, alat ini membuat baseline; pada eksekusi berikutnya, alat ini membandingkan dan mendeteksi kegagalan jika terdapat perbedaan. Perbarui baseline secara sengaja menggunakan --update-snapshots .

Tiga catatan praktis.

Garis dasar bersifat spesifik platform. Render font berbeda antar sistem operasi, sehingga garis dasar yang dihasilkan di macOS tidak akan cocok dengan yang dihasilkan di kontainer Linux. Buat garis dasar di lingkungan yang sama dengan tempat pengujian Anda berjalan — biasanya di CI, biasanya melalui kontainer yang juga dapat Anda jalankan secara lokal.

Tentukan batas toleransi. Pencocokan piksel yang tepat akan menghasilkan kegagalan akibat perbedaan antialiasing yang tidak akan disadari oleh manusia. Pengaturan maxDiffPixels` ` atau maxDiffPixelRatio dalam konfigurasi Anda adalah kunci agar rangkaian pengujian ini dapat digunakan.

Sembunyikan semua variabel sebelum memulai. Pengujian visual yang gagal setiap kali cap waktu berubah akan dinonaktifkan dalam waktu seminggu, yang lebih buruk daripada tidak memilikinya sama sekali.

Tangkapan Layar Melalui Proxy

Ini adalah kasus di mana hal ini benar-benar menjadi bidang keahlian kami, dan ini merupakan hal yang bagus.

Konfigurasikan proxy dalam pengaturan Playwright Anda:

const context = await browser.newContext({
  proxy: { server: 'http://proxy.example.com:9000', username: 'u', password: 'p' },
  locale: 'de-DE',
  timezoneId: 'Europe/Berlin',
});

Perhatikan locale

dan timezoneId

di samping proxy. Alamat keluar di Jerman dengan pengaturan wilayah en-US

dan zona waktu London adalah kombinasi yang tidak akan digunakan oleh pengunjung sungguhan, dan banyak situs menggunakan pengaturan wilayah secara terpisah dari alamat untuk menentukan konten apa yang akan ditampilkan. Atur ketiganya secara bersamaan, atau Anda akan menguji hal lain daripada yang Anda maksudkan.

Apa yang benar-benar dijawab oleh hal ini: apa yang dilihat oleh pengunjung asli di negara tersebut. Harga regional, tampilan mata uang, ketersediaan, spanduk promosi, apakah iklan Anda ditayangkan di tempat yang Anda bayar, dan apa yang muncul di samping konten Anda. Tidak ada API yang memberikan informasi ini, karena jawabannya adalah halaman yang telah dirender.

Berapa biayanya, dan bagaimana menguranginya. Browser mengambil semua data. Pada lalu lintas internet rumah tangga yang dibatasi kuota — tarif kami mulai dari $0,79/GB, diperiksa pada September 2026 berdasarkan halaman harga — pengambilan tangkapan layar di dua puluh pasar akan dengan cepat menumpuk biayanya. Memblokir jenis sumber daya yang tidak Anda butuhkan adalah langkah paling efektif:

await page.route('**/*.{woff,woff2,mp4,webm}', route => route.abort());

Perhatikan apa yang tidak ada dalam daftar tersebut. Jika tangkapan layar adalah hasil akhir yang diharapkan, Anda tidak bisa memblokir gambar — hal itu akan menghilangkan tujuan utama. Blokir font dan media, pertahankan gambar, dan terima kenyataan bahwa verifikasi visual pada dasarnya adalah jenis pekerjaan proxy yang mahal. Jika Anda hanya perlu memverifikasi konten teks daripada tampilan, blokir gambar juga dan lewati tangkapan layar sepenuhnya.

Dan pastikan geolokasi yang ditampilkan benar-benar sesuai. Ambil tangkapan layar dan periksa. Jika halaman yang ditangkap melalui exit server Brasil menunjukkan harga yang sama dengan yang ada di kantor Anda, penargetan tidak berfungsi terlepas dari apa yang dilaporkan oleh pencarian IP. Inilah kegagalan diam-diam yang kami jelaskan dalam mengapa pengujian proxy penting — dan tangkapan layar sangat efektif dalam mendeteksinya, karena manusia dapat melihatnya dalam sekejap.

Tangkapan Layar dalam Skala Besar

Begitu Anda mengambil lebih dari sekadar beberapa tangkapan layar, ada beberapa praktik yang dapat mencegah pekerjaan ini menjadi sulit dikendalikan.

Gunakan kembali browser, bukan konteksnya. Membuka browser membutuhkan sumber daya yang besar; sementara membuat konteks relatif hemat sumber daya. Untuk proses yang mencakup banyak halaman atau wilayah, jalankan sekali saja dan buat konteks baru per unit pekerjaan — hal ini memberi Anda cookie dan penyimpanan yang terisolasi tanpa harus membayar biaya awal berulang kali:

const browser = await chromium.launch();
for (const country of countries) {
  const ctx = await browser.newContext({ proxy: { server: proxyFor(country) } });
  const page = await ctx.newPage();
  await page.goto(url, { waitUntil: 'domcontentloaded' });
  await page.screenshot({ path: `shots/${country}.png`, fullPage: true });
  await ctx.close();
}
await browser.close();

Jangan gunakan networkidle sebagai kondisi tunggu Anda. Halaman dengan beacon analitik, websocket, atau polling tidak pernah dalam keadaan idle, sehingga waktu tunggu akan habis. Tunggu hingga elemen yang menandakan halaman sudah siap:

await page.goto(url);
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
await page.screenshot({ path: 'shot.png' });

Batasi jumlah proses yang berjalan secara bersamaan dengan sengaja. Setiap konteks browser mengonsumsi memori fisik — beberapa ratus megabita adalah hal yang wajar setelah halaman dimuat. Menjalankan tiga puluh proses secara paralel pada runner kecil akan menyebabkan kegagalan yang tampak seperti timeout, padahal sebenarnya mesin kehabisan ruang. Mulailah dengan empat atau lima dan tingkatkan sambil memantau memori.

Beri nama file agar mudah ditemukan. Direktori dengan nama screenshot-1.png hingga screenshot-400.png tidak dapat digunakan. Sertakan target, wilayah, dan cap waktu dalam nama file, serta simpan URL bersama gambar tersebut.

Kompres sebelum mengarsipkan. Format PNG tidak kehilangan kualitas tetapi ukurannya besar. Jika gambar dimaksudkan untuk tinjauan manusia, bukan perbandingan piksel, format JPEG di quality: 80 biasanya berukuran jauh lebih kecil dan secara visual tidak dapat dibedakan — dan untuk eksekusi di dua puluh pasar sesuai jadwal, perbedaan tersebut akan berdampak pada biaya penyimpanan.

Tangani kegagalan tanpa menghentikan proses. Satu halaman yang tidak dapat dimuat tidak boleh membuat sembilan belas halaman lainnya terabaikan. Selesaikan setiap penangkapan, catat kesalahannya, dan lanjutkan — kemudian laporkan target mana saja yang gagal, daripada baru menyadari bahwa seluruh pekerjaan gagal pada target ketiga.

Kapan Tangkapan Layar Bukanlah Alat yang Tepat

Saat Anda menginginkan datanya. Jika Anda membutuhkan harga, ambil saja harganya. Tangkapan layar dari sebuah angka hanyalah angka yang kemudian harus Anda baca dari sebuah gambar. Tangkapan layar diperuntukkan bagi tampilan; selektor diperuntukkan bagi konten.

Ketika Anda ingin tahu mengapa sebuah tes gagal. Jejak (trace) jauh lebih informatif dan tetap menyertakan tangkapan layar.

Ketika halaman tersebut sangat besar. Tangkapan layar penuh dari halaman dengan gulir tak terbatas menghasilkan file besar yang tidak akan dibuka oleh siapa pun. Potong saja ke bagian yang penting.

Ketika Anda memeriksa teks. Lakukan pengujian pada teks. Pengujian "expect(locator).toHaveText()" memberikan pesan kegagalan yang mudah dibaca; sedangkan perbandingan piksel hanya memberikan gambar dari teks tersebut.

Saat Anda perlu mengarsipkannya dalam skala besar. Tangkapan layar berukuran besar, dan ribuan tangkapan layar di berbagai pasar akan membebani penyimpanan serta bandwidth. Simpan hash atau perbandingan, dan simpan gambar lengkap hanya jika ada perubahan.

Pertanyaan Lainnya

Bagaimana cara mengambil tangkapan layar di Playwright? Gunakan `

`await page.screenshot({ path: 'shot.png' })untuk area tampilan,{ fullPage: true }untuk seluruh halaman yang dapat digulir, danlocator.screenshot()untuk satu elemen. Hilangkanpath`` untuk menyimpan ke buffer alih-alih menulis ke berkas.

Bagaimana cara mengambil tangkapan layar seluruh halaman?

Gunakan fullPage: true. Perhatikan bahwa konten yang dimuat secara tertunda mungkin belum muncul dan elemen yang menempel atau tetap dapat berperilaku aneh pada hasil yang disatukan — gulir halaman terlebih dahulu dengan sengaja, dan gunakan opsi style untuk menetralkan posisi elemen yang menempel selama proses pengambilan.

Bagaimana cara mengambil tangkapan layar satu elemen saja?

Panggil screenshot() pada sebuah locator, bukan pada halaman: await page.getByTestId('card').screenshot({ path: 'card.png' }). Playwright akan menggulir elemen tersebut hingga terlihat dan menangkap kotak pembatasnya. Konten yang dipotong oleh overflow: hidden tidak akan disertakan.

Bagaimana cara membuat tangkapan layar Playwright konsisten antar eksekusi?

Atur animations: 'disabled' dan caret: 'hide', tutupi area variabel dengan mask, dan atur scale secara eksplisit. Kemudian tetapkan ukuran viewport, locale, zona waktu, dan font yang tersedia, karena keempatnya memengaruhi tata letak dan tidak ada satupun yang merupakan opsi tangkapan layar.

Bagaimana cara mengambil tangkapan layar secara otomatis saat tes gagal?

Atur screenshot: 'only-on-failure' di blok use pada konfigurasi Playwright Anda. Gabungkan dengan trace: 'retain-on-failure' — jejak (trace) mencakup snapshot DOM, aktivitas jaringan, dan waktu eksekusi aksi, yang menjelaskan penyebab kegagalan alih-alih hanya menampilkannya.

Bisakah saya mendapatkan tangkapan layar dalam format base64 alih-alih berkas?

Ya. Hilangkan opsi path, dan screenshot() akan mengembalikan buffer, yang dapat Anda konversi menggunakan buffer.toString('base64'). Dokumen menyarankan hal ini untuk pemrosesan lanjutan atau pengiriman ke layanan perbandingan piksel, serta menghindari penggunaan sistem berkas pada runner CI yang bersifat sementara.

Bagaimana cara menyembunyikan konten dinamis dari tangkapan layar?

Gunakan opsi mask dengan array penanda lokasi, yang akan mengganti wilayah-wilayah tersebut dengan warna solid — maskColor secara default menggunakan #F0F dan dapat diubah. Inilah cara agar perbandingan visual tetap berguna pada halaman yang berisi cap waktu, data sesi, atau iklan.

Bisakah saya mengambil tangkapan layar melalui proxy untuk melihat halaman regional?

Ya, dan ini adalah salah satu kegunaan terbaik dari proxy. Atur proxy pada konteks browser, lalu atur locale dan timezoneId agar sesuai dengan negara — banyak situs menggunakan pengaturan wilayah secara independen dari alamat. Selanjutnya, periksa gambar hasilnya untuk memastikan bahwa konten regional benar-benar berbeda, daripada hanya mengandalkan pencarian IP.

Kesimpulan

Mengambil tangkapan layar di Playwright hanya butuh satu baris kode. Namun, untuk mengambil tangkapan layar yang bermakna, dibutuhkan sedikit usaha ekstra.

Jika tangkapan layar tersebut dimaksudkan untuk dilihat oleh manusia secara langsung — misalnya, bukti kegagalan, laporan bug, atau pengecekan tampilan halaman dari Brasil — pengaturan default sudah cukup, dan baris screenshot: 'only-on-failure' dalam konfigurasi Anda adalah baris paling berharga yang bisa Anda tambahkan. Padukan dengan trace, karena trace menjelaskan apa yang hanya ditampilkan oleh tangkapan layar.

Jika tangkapan layar akan dibandingkan dengan tangkapan layar lain, segalanya berubah. Nonaktifkan animasi, sembunyikan kursor, tutupi area variabel, tetapkan skala, dan atur viewport, locale, zona waktu, serta font. Kemudian buat baseline di lingkungan yang sama dengan tempat pengujian dijalankan, karena rendering font berbeda antar platform dan baseline dari laptop Anda tidak akan pernah cocok dengan container.

Dan untuk verifikasi geografis — di mana halaman yang dirender benar-benar lebih unggul daripada data terstruktur — atur proxy, pengaturan wilayah, dan zona waktu secara bersamaan, lalu periksa gambar untuk memastikan penargetan berhasil. Bandwidth adalah biayanya, gambar adalah satu-satunya jenis sumber daya yang tidak dapat Anda blokir, dan itulah biaya verifikasi visual.