AI
Playwright MCP vs Browser Use vs Stagehand: Browser Agent
Oktober 202612 menit baca

Playwright MCP adalah lapisan tool: ia menyediakan aksi browser seperti browser_click dan browser_snapshot untuk MCP client dan menyerahkan perencanaan ke client tersebut. Browser Use adalah agent framework Python yang class Agent-nya menjalankan sendiri seluruh loop mengamati, memutuskan dan bertindak. Pilih Playwright MCP untuk memberi browser pada agent yang sudah ada, dan Browser Use ketika Anda ingin framework yang mengendalikan task terbuka.
Tidak di v4. Panduan migrasi Stagehand menyatakan v4 mengendalikan Chromium lewat Chrome DevTools Protocol tanpa dependency Playwright, sehingga Page Playwright tidak bisa diberikan ke act. Memindahkan flow Playwright ke Stagehand v4 berarti melakukan porting, termasuk menambahkan wait eksplisit, karena v4 tidak melakukan auto-wait seperti Playwright.
Tidak. Playwright MCP bekerja dari structured accessibility snapshot, di mana setiap elemen interaktif punya ref yang diteruskan model ke tool seperti browser_click. Tool berbasis koordinat hanya tersedia jika Anda mengaktifkannya dengan flag --caps vision. Tool berbasis screenshot seperti computer tool OpenAI atau computer use Gemini lebih cocok untuk halaman yang di-render di canvas.
Jauhkan secret mentah dari context model. Browser Use menggantinya dengan placeholder lewat sensitive_data dan memberi warning jika allowed_domains tidak diisi, sedangkan Stagehand mengirimnya sebagai variables di act sehingga hanya nama placeholder yang sampai ke model. Matikan vision di layar yang menampilkan kredensial, dan pulihkan login dari file storage state alih-alih menyuruh model mengetiknya.
Tidak. README Playwright MCP menyatakan daftar allowed dan blocked origin-nya bukan security boundary dan tidak memengaruhi redirect. Terapkan allow list di lapisan network atau proxy, jalankan setiap session di container terisolasi, dan wajibkan konfirmasi manusia sebelum pembelian, transmisi data atau perubahan destruktif, seperti yang direkomendasikan panduan computer use OpenAI.

Ringkasan Utama
Playwright MCP, Browser Use dan Stagehand terutama berbeda pada siapa yang memegang agent loop. Playwright MCP menyediakan tool berbasis accessibility tree dan menyerahkan perencanaan ke client Anda. Browser Use menjalankan agent loop Python sendiri. Stagehand v4 menyediakan act, extract dan observe lewat CDP, tanpa Playwright. Computer-use tools OpenAI dan Gemini bekerja dari screenshot.
Bayangkan tim accounts payable di sebuah distributor di Indonesia. Empat puluh supplier masing-masing punya portal invoice sendiri, tidak satu pun menyediakan API, dan setiap pagi seseorang harus login ke tiap portal untuk mengecek invoice mana yang sudah dibayar, disengketakan, atau masih terbuka. Ini kasus klasik untuk browser agent, dan pencarian pertama, playwright mcp vs browser use, memunculkan empat jenis tool yang sangat berbeda tetapi sama-sama mengaku bisa menyelesaikannya.
Keempatnya tidak menyelesaikan masalah yang sama. Artikel ini membandingkan Playwright MCP, Browser Use, Stagehand, serta computer-use tools dari OpenAI dan Google pada pertanyaan yang menentukan build production: siapa yang memegang loop, apakah model membaca DOM atau melihat piksel, berapa biaya run berulang, dan di mana kontrol keamanan sebenarnya berada. Semua nama API dan nilai default di bawah diambil dari dokumentasi terkini tiap proyek, dengan sumber di bagian akhir.
Browser agent pada dasarnya sebuah loop: lihat halaman, tentukan langkah berikutnya, bertindak, lalu lihat lagi. Tool dalam perbandingan ini terbagi jelas berdasarkan bagian loop mana yang mereka sediakan dan bagian mana yang diserahkan kepada Anda.
Makin ke bawah daftar itu, makin besar bagian loop yang menjadi kode Anda sendiri, dan makin besar pula tanggung jawab Anda atas reliabilitasnya. Ini bukan peringkat. Framework yang memegang loop paling cepat menghasilkan demo, sedangkan memegang loop sendiri memungkinkan Anda memasang langkah approval tepat di titik aksi menjadi tidak bisa dibatalkan.
Tabel berikut menyandingkan keempat pendekatan pada dimensi yang benar-benar mengubah keputusan arsitektur. Kolom vendor menggabungkan OpenAI dan Gemini karena bentuknya sama: screenshot masuk, aksi keluar.
| Dimensi | Playwright MCP | Browser Use | Stagehand v4 | Computer-use tools |
|---|---|---|---|---|
| Siapa yang memegang loop | MCP client atau agent Anda | Class Agent milik framework | Kode Anda, langkah demi langkah | Kode Anda menjalankan aksi yang dikembalikan model |
| Apa yang dilihat model | Accessibility snapshot dengan ref elemen; tidak perlu vision model | State DOM plus screenshot; use_vision default True | Konten halaman per call, di-resolve menjadi selector | Hanya screenshot |
| Cara menargetkan elemen | Ref dari snapshot terakhir, atau selector | Index elemen yang dipilih agent | Instruksi bahasa alami, atau observed action yang di-replay | Koordinat piksel; Gemini memakai grid 0 sampai 1000 |
| Bahasa dan runtime | MCP server Node lewat stdio, untuk MCP client apa pun | Python 3.11 ke atas, plus edisi TypeScript | TypeScript, Python dan Go, lewat CDP | Bahasa apa pun yang memanggil Responses API atau Gemini API |
| Biaya run berulang | Setiap langkah adalah satu giliran model di client Anda | Setiap langkah adalah satu model call | Observed action di-replay tanpa LLM call; server cache di Browserbase | Setiap langkah adalah model call dengan gambar |
| Penanganan secret | --secrets menyamarkan teks yang cocok di response, sekadar kemudahan | Placeholder sensitive_data, dibatasi per domain | variables di act; hanya nama placeholder yang sampai ke model | Anda bangun sendiri; mengetik data sensitif dihitung sebagai transmisi |
| Lisensi dan hosting | Apache-2.0 dari Microsoft, jalan lokal atau di Docker | Library MIT; cloud browser opsional 0,02 USD per browser-hour | MIT; browser lokal atau session Browserbase | API model yang di-host; browser atau VM Anda yang host |
| Paling cocok untuk | Memberi browser pada coding agent atau chat agent yang sudah ada | Task terbuka yang jalurnya belum diketahui | Flow berulang yang harus tahan perubahan layout | Aplikasi canvas, aplikasi desktop, halaman dengan accessibility buruk |
Dua baris memikul sebagian besar keputusan. Persepsi menentukan situs mana yang bisa dipakai sama sekali: accessibility tree murah dan presisi pada form yang dibangun dengan baik, tetapi hampir tidak berguna pada dashboard yang di-render di canvas, di mana hanya screenshot yang membantu. Biaya run berulang menentukan apakah flow itu terjangkau untuk empat puluh portal setiap pagi, dan hanya Stagehand yang punya cara bawaan untuk berhenti membayar model atas langkah yang sudah direncanakan.
Playwright MCP adalah server Model Context Protocol dari Microsoft yang membungkus Playwright. README-nya menjelaskan bahwa ia bekerja lewat structured accessibility snapshot, tanpa perlu screenshot atau model yang dilatih untuk visual. Model membaca tree berisi role dan nama, setiap node interaktif diberi ref, lalu meneruskan ref itu ke tool seperti browser_click, browser_type dan browser_fill_form.
// .mcp.json (or your client's mcpServers block)
{
"mcpServers": {
"playwright": {
"command": "npx",
"args": [
"@playwright/mcp@latest",
"--headless",
"--isolated", // profile lives in memory, gone on close
"--storage-state", "./portal-auth.json", // log in once, outside the agent
"--allowed-origins", "https://portal.supplier.example",
"--secrets", "./.portal.env" // masks matching text in tool responses
]
}
}
}
// What the model actually reads: an accessibility snapshot, not pixels.
// browser_snapshot returns a tree; every interactive node carries a ref.
// - heading "Open invoices" [level=1]
// - textbox "Invoice number" [ref=e14]
// - button "Search" [ref=e15]
// - row "INV-2026-0912 Rp 48.250.000 Unpaid" [ref=e31]
//
// The model then calls a tool with that ref as the target:
// browser_type { "target": "e14", "text": "INV-2026-0912" }
// browser_click { "target": "e15", "element": "Search button" }
//
// The planning loop is YOURS (or your MCP client's). Playwright MCP
// executes one tool call and returns the new snapshot. Nothing more.Server ini tidak pernah merencanakan. Ia menjalankan tool yang diminta dan melaporkan state baru, sehingga kualitas agent sepenuhnya ditentukan oleh MCP client dan model di belakangnya. Itu kekuatan ketika client-nya sudah agent yang cakap, dan itulah alasan Playwright MCP menjadi cara umum memberi browser pada Claude Code, Cursor atau VS Code. Tool berbasis koordinat seperti browser_mouse_click_xy memang ada, tetapi hanya aktif jika Anda opt in dengan --caps vision.
Baca dokumentasi flag dengan teliti sebelum mengandalkannya untuk keamanan. README menyatakan bahwa --allowed-origins dan --blocked-origins bukan security boundary dan tidak memengaruhi redirect, bahwa opsi secrets hanyalah kemudahan dan bukan fitur keamanan, dan di bagian security-nya, bahwa Playwright MCP bukan security boundary. Profil persisten adalah default dan hanya bisa dipakai satu instance browser sekaligus, jadi client paralel butuh --isolated atau path --user-data-dir yang berbeda.
Jika pemanggilnya coding agent, bukan chat agent, baca dulu saran README Playwright MCP sendiri. README itu merekomendasikan Playwright CLI terpisah beserta skills untuk coding agent, karena pemanggilan CLI tidak perlu memuat tool schema yang besar dan accessibility tree yang panjang ke context window. Pakai MCP ketika agent butuh state browser yang persisten di sepanjang banyak langkah reasoning.
Browser Use adalah library Python berlisensi MIT, dengan edisi TypeScript, yang class Agent-nya memegang loop. Anda memberikan task, model, dan opsional Browser serta Tools kustom; agent.run menjalankan langkah sampai model memanggil done atau max_steps habis. Contoh di bawah memberi agent satu tool kustom yang sempit untuk menulis draft note ke ERP, alih-alih membiarkannya menyentuh layar ERP.
import asyncio
from browser_use import ActionResult, Agent, Browser, ChatBrowserUse, Tools
tools = Tools()
# Give the agent a door into YOUR system instead of letting it type into the ERP UI.
@tools.action(description="Record a supplier invoice status as a DRAFT note in the ERP.")
def save_invoice_status(invoice_no: str, status: str) -> ActionResult:
draft_id = erp_client.create_draft_note(invoice_no, status) # your code
return ActionResult(extracted_content=f"draft {draft_id} saved")
async def main():
agent = Agent(
task="Log in with x_user / x_pass, open Open invoices, "
"read the status of INV-2026-0912 and save it with save_invoice_status.",
llm=ChatBrowserUse(model="bu-2-0"),
browser=Browser(allowed_domains=["https://portal.supplier.example"]),
tools=tools,
# The model only ever sees the placeholder names x_user and x_pass.
sensitive_data={"https://portal.supplier.example":
{"x_user": PORTAL_USER, "x_pass": PORTAL_PASS}},
use_vision=False, # default is True: screenshots would show the password field
max_failures=3, # default 5
step_timeout=120, # seconds, default 180
)
history = await agent.run(max_steps=25)
# is_successful() is what the AGENT reports. Check the ERP draft yourself.
print(history.is_successful(), history.final_result())
asyncio.run(main())Nilai default-nya disetel untuk menyelesaikan task, bukan untuk berhati-hati. run menerima max_steps dengan default 500 di source terkini, use_vision bernilai True, max_failures dan max_actions_per_step sama-sama 5, dan step_timeout 180 detik. Untuk pekerjaan back office, turunkan batas langkah, matikan vision setiap kali kredensial tampil di layar, dan isi allowed_domains: library ini sendiri mencatat warning ketika sensitive_data diisi tanpa allowed_domains, karena halaman yang terkena prompt injection bisa membaca balik secret tersebut.
Agent yang sama juga bisa dijalankan sebagai MCP server lokal dengan uvx dan extra CLI browser-use, yang membalik hubungannya dengan Playwright MCP: chat client Anda mendelegasikan seluruh sub-task browsing ke Browser Use, bukan mengendalikan setiap klik. Perhatikan bahwa history.is_successful melaporkan klaim agent. Dokumentasi Browser Use menyebutkan hal ini secara langsung dan menyarankan aksi eksternal yang penting diverifikasi secara terpisah.
Stagehand dari Browserbase berada di antara selector yang ditulis manual dan agent yang berjalan bebas. Anda menulis flow-nya; act menjalankan satu langkah bahasa alami, extract mengembalikan data yang divalidasi dengan schema Zod, dan observe mengembalikan kandidat aksi berisi selector, description, method dan arguments. Mengirim salah satu observed action itu kembali ke act akan me-replay-nya tanpa LLM call, dan begitulah flow yang direncanakan sekali menjadi murah untuk dijalankan ulang.
Sebagian besar perbandingan masih menggambarkan Stagehand sebagai lapisan di atas Playwright. Untuk v4, itu sudah usang. Panduan migrasinya menyatakan v4 mengendalikan Chromium lewat Chrome DevTools Protocol tanpa dependency Playwright, sehingga Page Playwright tidak bisa diberikan ke act dan memindahkan flow berarti melakukan porting. v4 juga menghapus agent, enableCaching dan cacheDir.
import { localBrowser, Stagehand } from "@browserbasehq/stagehand";
import { z } from "zod";
const browser = await localBrowser.launch();
const stagehand = await Stagehand.create({
browser,
model: { modelName: "openai/gpt-5.6-sol", apiKey: process.env.OPENAI_API_KEY },
});
const [page] = await browser.context.pages();
await page.goto("https://portal.supplier.example/login");
// Wrong: one act() with "log in, open invoices and search for 0912".
// Right: one atomic step per act(). Secrets go in as variables; only the
// placeholder name reaches the model provider.
await stagehand.act("type %user% into the username field", { variables: { user: PORTAL_USER } });
await stagehand.act("type %pass% into the password field", { variables: { pass: PORTAL_PASS } });
await stagehand.act("click the sign in button");
// v4 has NO Playwright-style auto-waiting: wait explicitly before the next step.
await page.waitForSelector("table.invoices");
// observe() plans once; act(action) replays the returned action with no LLM call.
const { data: searchSteps } = await stagehand.observe("find the invoice search box and its submit button");
for (const step of searchSteps) await stagehand.act(step);
const { data } = await stagehand.extract(
"extract every open invoice row",
z.object({ invoices: z.array(z.object({
number: z.string(), amountIdr: z.number(), status: z.string(),
})) }),
);
await stagehand.close();
await browser.close();Porting-nya bukan sekadar ganti nama. Stagehand.create menggantikan new Stagehand plus init, act, extract dan observe pindah ke instance Stagehand, dan setiap primitive mengembalikan pasangan data dan metadata. Detail yang paling diam-diam merusak script hasil porting adalah waiting: v4 me-resolve selector sekali dan langsung throw jika elemennya belum ada, berbeda dengan auto-waiting Playwright, sehingga panggilan waitForSelector eksplisit harus ditambahkan lagi.
Caching juga berubah di rilis yang sama. Direktori cache lokal dihapus; caching kini server-side di Browserbase, aktif secara default di sana, dengan key dari instruksi, konten halaman dan opsi call, dan sengaja tidak memasukkan model. Di browser lokal, pola observe lalu act adalah tuas biaya yang Anda kendalikan, dan dokumentasinya menyarankan satu langkah atomik per act call alih-alih merangkai beberapa langkah dalam satu instruksi.
Tool dari vendor melewati DOM sepenuhnya. Computer tool OpenAI di Responses API mengembalikan computer_call berisi daftar aksi yang berurutan dan di-batch, dari click, double_click, drag, move, scroll, keypress, type, wait dan screenshot. Kode Anda mengeksekusinya lalu menjawab dengan screenshot di computer_call_output. Tool computer_use Gemini bekerja dengan cara yang sama, dengan koordinat yang dinormalisasi ke grid 0 sampai 1000 yang harus Anda skala ke ukuran layar sebenarnya.
# ── OpenAI: the computer tool in the Responses API ──
response = client.responses.create(
model="gpt-6.1-sol",
tools=[{"type": "computer"}],
input="Open the Open invoices page and read the status of INV-2026-0912.",
)
# The output holds a computer_call with an ORDERED, batched actions array:
# {"type": "computer_call", "call_id": "call_002", "actions": [
# {"type": "click", "button": "left", "x": 405, "y": 157},
# {"type": "type", "text": "INV-2026-0912"}]}
# Allowed: click, double_click, drag, move, scroll, keypress, type, wait, screenshot.
for action in call.actions:
if not policy.allows(action): # your allow list, your confirmation step
raise NeedsHuman(action)
execute(page, action) # Playwright, PyAutoGUI, a VM ...
response = client.responses.create(
model="gpt-6.1-sol",
tools=[{"type": "computer"}],
previous_response_id=response.id,
input=[{"type": "computer_call_output", "call_id": call.call_id,
"output": {"type": "computer_screenshot",
"image_url": f"data:image/png;base64,{png_b64}",
"detail": "original"}}],
)
# ── Gemini: the computer_use tool, coordinates on a 0-1000 grid ──
tools = [{"type": "computer_use", "environment": "browser"}]
def to_px(x, y, width=1440, height=900): # 1440x900 is the suggested browser size
return int(x / 1000 * width), int(y / 1000 * height)
# A function_call may arrive with safety_decision = require_confirmation.
# Treat that as a hard stop for a human, not a hint.Dua detail penting bagi siapa pun yang membangun di atasnya sekarang. Panduan OpenAI merekomendasikan code execution, di mana model menulis script Playwright atau PyAutoGUI, dibanding computer tool terstruktur untuk model terbarunya, dan menyediakan bagian migrasi untuk integrasi yang dibangun di atas computer-use-preview lama. Gemini menandai computer use sebagai kapabilitas Preview yang bisa mengandung error dan celah keamanan, dan response-nya bisa membawa safety_decision bernilai require_confirmation, yang harus diubah loop Anda menjadi jeda nyata untuk manusia.
Produk consumer yang dibangun dari ide ini juga tidak stabil. Operator diluncurkan pada Januari 2025 dan ditutup pada 31 Agustus 2025 setelah diserap ChatGPT agent, dan ChatGPT agent sendiri dihapus dari ChatGPT pada awal Agustus 2026 tanpa pemberitahuan sebelumnya. Untuk proses bisnis, riwayat itu menjadi alasan untuk membangun di lapisan API yang Anda kendalikan, bukan di satu asisten hosted tertentu.
Setiap tool dalam perbandingan ini menyatakan, di dokumentasinya sendiri, bahwa ia tidak akan menjauhkan halaman jahat atau model yang bingung dari data Anda. Kontrolnya harus ada di environment Anda. Checklist minimal untuk agent portal supplier:
Perlakukan semua yang tampil di layar sebagai input yang tidak tepercaya. Panduan OpenAI menyatakan teks di halaman, dokumen atau tool result tidak bisa memberi izin atau mengesampingkan instruksi user. Portal supplier bisa saja memuat catatan yang menyuruh agent mengirim invoice ke alamat lain, dan hanya loop yang Anda kendalikan yang bisa menolaknya.
Untuk skenario accounts payable tadi, pilihannya mengikuti seberapa jelas jalurnya dan siapa yang akan memeliharanya. Pembagian yang masuk akal:
Apa pun yang menjalankan browser, jauhkan operasi tulis darinya. Agent membaca portal dan menyerahkan data terstruktur ke kode Anda sendiri, yang membuat draft di ERP untuk di-posting oleh manusia. Dengan begitu browser agent tetap mudah diganti, dan itu penting di kategori di mana Stagehand membuang Playwright dan method agent-nya dalam satu major version.
Aturan yang berguna adalah memilih berdasarkan kepemilikan loop, bukan judul benchmark. Serahkan loop ke Browser Use ketika jalurnya belum diketahui, pegang sendiri dengan Stagehand ketika jalurnya berulang, pinjamkan tool ke agent yang sudah ada dengan Playwright MCP, dan pakai screenshot hanya ketika tidak ada DOM yang layak dibaca. Dalam semua kasus, security boundary adalah tanggung jawab Anda untuk dibangun.