[{"data":1,"prerenderedAt":699},["ShallowReactive",2],{"tool-webmcp-en":3},{"slug":4,"published":5,"minutes":6,"category":7,"tags":8,"keywords":14,"about":21,"sources":29,"cover":53,"og":54,"expertise":55,"locales":56,"lang":57,"title":60,"description":61,"coverAlt":62,"url":63,"pricing":64,"kind":65,"metaTitle":66,"takeaways":67,"faq":73,"toc":86,"blocks":111,"others":475},"webmcp","2026-09-30",11,"web",[9,10,11,12,13],"WebMCP","Agent tools","JSON Schema","Chrome","MCP",[4,15,16,17,18,19,20],"webmcp vs mcp","document.modelContext registerTool","webmcp declarative api","browser agent tools","webmcp origin trial","webmcp chrome 149",[22,24,27],{"name":9,"url":23},"https:\u002F\u002Fgithub.com\u002Fwebmachinelearning\u002Fwebmcp",{"name":25,"url":26},"Model Context Protocol","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FModel_Context_Protocol",{"name":11,"url":28},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FJSON_Schema",[30,33,36,39,42,45,48,50],{"title":31,"url":32},"Chrome for Developers: WebMCP (get started)","https:\u002F\u002Fdeveloper.chrome.com\u002Fdocs\u002Fai\u002Fwebmcp",{"title":34,"url":35},"Chrome for Developers: Imperative API","https:\u002F\u002Fdeveloper.chrome.com\u002Fdocs\u002Fai\u002Fwebmcp\u002Fimperative-api",{"title":37,"url":38},"Chrome for Developers: Declarative API","https:\u002F\u002Fdeveloper.chrome.com\u002Fdocs\u002Fai\u002Fwebmcp\u002Fdeclarative-api",{"title":40,"url":41},"Chrome for Developers: WebMCP versus MCP","https:\u002F\u002Fdeveloper.chrome.com\u002Fdocs\u002Fai\u002Fwebmcp\u002Fcompare-mcp",{"title":43,"url":44},"Chrome for Developers: WebMCP tool security","https:\u002F\u002Fdeveloper.chrome.com\u002Fdocs\u002Fai\u002Fwebmcp\u002Fsecure-tools",{"title":46,"url":47},"Chrome for Developers: Build effective tools","https:\u002F\u002Fdeveloper.chrome.com\u002Fdocs\u002Fai\u002Fwebmcp\u002Fbuild-tools",{"title":49,"url":23},"WebMCP explainer and specification draft",{"title":51,"url":52},"WebMCP implementation status","https:\u002F\u002Fgithub.com\u002Fwebmachinelearning\u002Fwebmcp\u002Fblob\u002Fmain\u002Fimplementation-status.md","\u002Fimages\u002Fblog\u002Fwebmcp\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fwebmcp\u002Fog.jpg","ai-engineer",[57,58,59],"en","de","hu","WebMCP: publishing tools instead of pixels","WebMCP lets a page publish typed, callable tools to an in-browser agent. What the standard does, how much of it ships today, and where a plain MCP server is still the better call.","A page registering typed tools with the browser, a browser agent calling one of them, and the tool running inside the page and updating its own interface.","https:\u002F\u002Fgithub.com\u002Fwebmcp","Emerging standard, open","Browser protocol","WebMCP: publishing tools instead of pixels · Balázs Csorba",[68,69,70,71,72],"WebMCP is a browser API proposal, not a library: Chrome 149 and Edge 150 ship it as an origin trial, and Firefox and Safari are at the standards-position stage.","Tools are tab-bound, run the page's own code, and are gated by the tools Permissions Policy rather than by an agent guessing at the DOM.","Chrome's guidance caps a tool description at 500 characters and a tool's output at 1.5K, so the tool catalogue is a context-window budget.","All four tool annotations default to false, which makes a tool's safety properties exactly as honest as the page that sets them.","There is no discovery mechanism: a client has to visit the site to learn that tools exist, which changes what the standard is commercially worth.",[74,77,80,83],{"q":75,"a":76},"What is WebMCP?","WebMCP is a proposed web standard that lets a page publish typed, callable tools to an AI agent running in the browser. A page registers a name, a natural-language description, a JSON Schema for the input and an execute function, and the browser mediates calls between the agent and that function. The tools live only as long as the tab is open.",{"q":78,"a":79},"Is WebMCP a replacement for MCP?","No. Chrome's own comparison page treats the two as partners rather than rivals: MCP exposes backend capabilities to any client, persistently, while WebMCP exposes live page state to a browser-integrated agent, ephemerally. Most production setups end up using both, with MCP for business logic and WebMCP for the interface in front of the user.",{"q":81,"a":82},"Do I need the Chrome origin trial to use WebMCP locally?","No. For local development, the chrome:\u002F\u002Fflags\u002F#enable-webmcp-testing flag enables it without a token. Serving real users on Chrome 149 or later does require registering for the origin trial, and Edge 150 runs a separate trial with its own registration.",{"q":84,"a":85},"What is the biggest limitation today?","Browser support, followed by discoverability. The implementation status file in the specification repository lists origin trials in Chrome and Edge, experimental support in Brave's Leo chat and support in ChatGPT Desktop, and nothing shipped in Firefox or Safari. On top of that, the API is not designed for headless browsing, and a client can only find out that a site has tools by visiting it.",[87,90,93,96,99,102,105,108],{"id":88,"title":89},"what-it-is","What it is",{"id":91,"title":92},"how-it-works","How it works",{"id":94,"title":95},"getting-started","Getting started",{"id":97,"title":98},"tool-design","Designing tools that agents pick",{"id":100,"title":101},"security","Security and annotations",{"id":103,"title":104},"where-it-shingles","Where it falls short",{"id":106,"title":107},"verdict","Verdict",{"id":109,"title":110},"sources","Sources",[112,116,119,122,134,193,194,197,206,209,210,213,215,222,226,229,231,249,256,257,260,288,291,323,324,327,349,352,362,363,366,412,415,416,425,438,447,448],{"type":113,"content":114},"paragraph",[115],"WebMCP is a proposed web standard that lets a page publish typed, callable tools to an AI agent instead of leaving the agent to infer intent from the DOM. The proposal is small, the browser support is thin, and the design decision is the right one. Treat it as a specification to track and a progressive enhancement to build behind feature detection, not as an integration to depend on this quarter.",{"type":113,"content":117},[118],"It sits beside Model Context Protocol rather than against it. An MCP server exposes backend capabilities to any client, anywhere; WebMCP exposes the live, signed-in, in-tab state of a page to a browser-integrated agent, and disappears when the tab closes. The interesting engineering question is not which protocol wins. It is which one can make existing front-end logic reachable without writing a server for it.",{"type":120,"level":121,"id":88,"text":89},"heading",2,{"type":113,"content":123},[124,125,129,130,133],"The specification lives in the W3C Web Machine Learning Community Group and is written up in the WebMCP explainer on GitHub, where the Chrome and Edge teams are the visible implementers. Chrome ships it behind an origin trial from Chrome 149, with a local development flag at ",{"tag":126,"children":127},"code",[128],"chrome:\u002F\u002Fflags\u002F#enable-webmcp-testing",". The API is one object on ",{"tag":126,"children":131},[132],"Document",", and it comes in two forms.",{"type":135,"ordered":136,"items":137},"list",false,[138,158,160,176,178,191],[139,142,143,146,147,146,150,153,154,157],{"tag":126,"children":140},[141],"document.modelContext"," exposes ",{"tag":126,"children":144},[145],"registerTool()",", ",{"tag":126,"children":148},[149],"getTools()",{"tag":126,"children":151},[152],"executeTool()"," and a ",{"tag":126,"children":155},[156],"toolchange"," event.",[159],"A tool is a name, a natural-language description, a JSON Schema for its input, and an execute function that runs inside the page.",[161,162,146,165,146,168,171,172,175],"The declarative API turns an annotated form into a tool, using ",{"tag":126,"children":163},[164],"toolname",{"tag":126,"children":166},[167],"tooldescription",{"tag":126,"children":169},[170],"toolparamdescription"," and ",{"tag":126,"children":173},[174],"toolautosubmit",".",[177],"Tools are ephemeral. They exist only while the page is open and they run with the page's own cookies and session.",[179,180,183,184,187,188,175],"Both APIs are gated by the ",{"tag":126,"children":181},[182],"tools"," Permissions Policy, which defaults to ",{"tag":126,"children":185},[186],"self",", so cross-origin iframes stay off unless the host adds ",{"tag":126,"children":189},[190],"allow=\"tools\"",[192],"Tool metadata sits in the model's context window, which makes the number of registered tools a per-page budget rather than only a code concern.",{"type":120,"level":121,"id":91,"text":92},{"type":113,"content":195},[196],"Registration is one call from page script; invocation is the browser mediating between the agent and the page. The browser never hands the agent a DOM handle. It parses the arguments, calls your execute function, and passes the return value back as the tool result. That is the whole ergonomics story in one sentence: the page decides what is callable, and the browser decides who may call it.",{"type":198,"attrs":199,"inner":203,"caption":204},"diagram",{"viewBox":200,"role":201,"aria-labelledby":202},"0 0 720 320","img","wm-t wm-d","\u003Ctitle id=\"wm-t\">WebMCP tool lifecycle\u003C\u002Ftitle>\u003Cdesc id=\"wm-d\">A page registers a tool on document.modelContext. The browser mediates: it lists the tools to the agent, the agent invokes one, the execute function runs in the page, the page updates its own DOM and state, and the result travels back through the browser to the agent.\u003C\u002Fdesc>\u003Cdefs>\u003Cmarker id=\"ah-wm\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\">\u003Cpath d=\"M0 0L10 5L0 10z\" class=\"d-head\" \u002F>\u003C\u002Fmarker>\u003C\u002Fdefs>\u003Crect x=\"20\" y=\"120\" width=\"160\" height=\"72\" rx=\"10\" class=\"d-box\" \u002F>\u003Ctext x=\"100\" y=\"150\" text-anchor=\"middle\" class=\"d-text\">your page\u003C\u002Ftext>\u003Ctext x=\"100\" y=\"172\" text-anchor=\"middle\" class=\"d-small\">registerTool()\u003C\u002Ftext>\u003Crect x=\"280\" y=\"120\" width=\"160\" height=\"72\" rx=\"10\" class=\"d-accent\" \u002F>\u003Ctext x=\"360\" y=\"150\" text-anchor=\"middle\" class=\"d-text\">model context\u003C\u002Ftext>\u003Ctext x=\"360\" y=\"172\" text-anchor=\"middle\" class=\"d-small\">browser-mediated\u003C\u002Ftext>\u003Crect x=\"540\" y=\"40\" width=\"160\" height=\"72\" rx=\"10\" class=\"d-sky\" \u002F>\u003Ctext x=\"620\" y=\"70\" text-anchor=\"middle\" class=\"d-text\">agent\u003C\u002Ftext>\u003Ctext x=\"620\" y=\"92\" text-anchor=\"middle\" class=\"d-small\">getTools()\u003C\u002Ftext>\u003Crect x=\"540\" y=\"200\" width=\"160\" height=\"72\" rx=\"10\" class=\"d-gold\" \u002F>\u003Ctext x=\"620\" y=\"230\" text-anchor=\"middle\" class=\"d-text\">execute()\u003C\u002Ftext>\u003Ctext x=\"620\" y=\"252\" text-anchor=\"middle\" class=\"d-small\">your app logic\u003C\u002Ftext>\u003Crect x=\"280\" y=\"230\" width=\"160\" height=\"72\" rx=\"10\" class=\"d-mint\" \u002F>\u003Ctext x=\"360\" y=\"260\" text-anchor=\"middle\" class=\"d-text\">DOM and state\u003C\u002Ftext>\u003Ctext x=\"360\" y=\"282\" text-anchor=\"middle\" class=\"d-small\">same session\u003C\u002Ftext>\u003Cpath d=\"M180 156H278\" class=\"d-line\" marker-end=\"url(#ah-wm)\" \u002F>\u003Cpath d=\"M360 120V76H538\" class=\"d-line\" marker-end=\"url(#ah-wm)\" \u002F>\u003Ctext x=\"450\" y=\"66\" text-anchor=\"middle\" class=\"d-label\">2 discover\u003C\u002Ftext>\u003Ctext x=\"228\" y=\"146\" text-anchor=\"middle\" class=\"d-label\">1 register\u003C\u002Ftext>\u003Cpath d=\"M620 112V198\" class=\"d-line-accent\" marker-end=\"url(#ah-wm)\" \u002F>\u003Ctext x=\"640\" y=\"160\" class=\"d-label\">3 invoke\u003C\u002Ftext>\u003Cpath d=\"M540 236H442\" class=\"d-line\" marker-end=\"url(#ah-wm)\" \u002F>\u003Ctext x=\"490\" y=\"226\" text-anchor=\"middle\" class=\"d-label\">4 update\u003C\u002Ftext>\u003Cpath d=\"M360 230V196\" class=\"d-line\" marker-end=\"url(#ah-wm)\" \u002F>\u003Ctext x=\"374\" y=\"218\" class=\"d-label\">5 result\u003C\u002Ftext>",[205],"The browser sits between the agent and the page. Nothing else in the loop can widen that boundary.",{"type":113,"content":207},[208],"The practical difference from actuation shows up in the error path. A click on a mis-rendered element fails silently or fires the wrong handler. A tool call with a bad argument hits your own validation and returns a message the model can read and act on. Chrome's guidance makes this explicit and advises validating strictly in code while keeping the schema loose, because a schema rejection is a dead end for the agent.",{"type":120,"level":121,"id":94,"text":95},{"type":113,"content":211},[212],"The imperative API is the one to reach for, because it is the only one that can touch application state. A minimal read-only tool looks like this.",{"type":126,"code":214},"\u002F\u002F Feature-detect: the API is behind a flag or an origin trial.\nif (typeof document.modelContext?.registerTool !== 'function') return;\n\nconst controller = new AbortController();\n\nawait document.modelContext.registerTool({\n  name: 'get_order_status',\n  description: 'Return the shipping status of one order for the signed-in customer.',\n  inputSchema: {\n    type: 'object',\n    properties: {\n      orderNumber: { type: 'string', description: 'Order number as shown in the order list.' },\n    },\n    required: ['orderNumber'],\n    additionalProperties: false,\n  },\n  annotations: { readOnlyHint: true },\n  execute: async ({ orderNumber }) => {\n    const order = await orders.findForCustomer(orderNumber);\n    \u002F\u002F A message the model can act on beats a thrown Error.\n    if (!order) return `No order ${orderNumber} is visible to this account.`;\n    return `Order ${orderNumber}: ${order.status}, arriving ${order.eta}.`;\n  },\n}, { signal: controller.signal });\n\n\u002F\u002F Unregister on route change. From Chrome 153 aborting no longer breaks a\n\u002F\u002F call that is already running.\ncontroller.abort();",{"type":113,"content":216},[217,218,221],"Three details matter more than the rest. The description is the only thing the model reads to decide whether to call the tool, and Chrome's guidance caps it at 500 characters. The execute function should reuse the function the visible button already calls, so there is one code path and no chance of the interface and the tool disagreeing. The ",{"tag":126,"children":219},[220],"AbortSignal"," is the unregister path, not a timeout.",{"type":120,"level":223,"id":224,"text":225},3,"declarative-forms","Declarative forms",{"type":113,"content":227},[228],"The declarative API is for plain forms and nothing else. Annotate a form element and the browser derives the tool definition from the markup and the field names.",{"type":126,"code":230},"\u003Cform toolname=\"create_support_request\"\n      tooldescription=\"Submits a support request for the signed-in customer.\"\n      action=\"\u002Fsupport\"\n      toolautosubmit>\n  \u003Clabel for=\"subject\">Subject\u003C\u002Flabel>\n  \u003Cinput id=\"subject\" name=\"subject\" type=\"text\">\n\n  \u003Clabel for=\"reason\">Reason\u003C\u002Flabel>\n  \u003Cselect id=\"reason\" name=\"reason\" required\n          toolparamdescription=\"Determines which team handles the request.\">\n    \u003Coption value=\"returns\">Return a purchase\u003C\u002Foption>\n    \u003Coption value=\"delivery\">Where is my parcel\u003C\u002Foption>\n    \u003Coption value=\"site\">The website is broken\u003C\u002Foption>\n  \u003C\u002Fselect>\n\n  \u003Cbutton type=\"submit\">Submit\u003C\u002Fbutton>\n\u003C\u002Fform>",{"type":113,"content":232},[233,234,236,237,240,241,244,245,248],"Without ",{"tag":126,"children":235},[174]," the agent fills the form and the human presses submit, which is the right default for anything with a cost attached. With it, the browser submits and navigates, and ",{"tag":126,"children":238},[239],"respondWith()"," on the ",{"tag":126,"children":242},[243],"SubmitEvent"," lets the page return a result to the model instead. The ",{"tag":126,"children":246},[247],"agentInvoked"," flag tells the page which of the two paths it is on.",{"type":250,"variant":251,"title":252,"body":253},"callout","note","The cheap half of the standard",[254],[255],"The declarative API cannot reach a JavaScript-only feature, because there is no JavaScript in the tool definition. OpenAI's site-tools documentation states that its built-in browser does not implement the declarative API at all, so a form-only integration is invisible to ChatGPT Work and Codex today.",{"type":120,"level":121,"id":97,"text":98},{"type":113,"content":258},[259],"The published best-practice guidance is unusually prescriptive, and it is worth following literally. The framing is that a tool description is code that a probabilistic reader has to interpret once per session, and the character budgets exist to keep the whole catalogue inside that reader's attention.",{"type":261,"head":262,"rows":267},"table",[263,265],[264],"Budget",[266],"Recommended limit",[268,273,278,283],[269,271],[270],"Tool description",[272],"500 characters",[274,276],[275],"Parameter description",[277],"150 characters",[279,281],[280],"Tool name and parameter name",[282],"30 characters each",[284,286],[285],"One tool's output",[287],"1.5K characters",{"type":113,"content":289},[290],"The advice above the table is the harder half: one tool per function, no overlap between tools, and registration tied to page state rather than a static catalogue loaded on every page. Overlapping tools are the most common reason an agent picks the wrong one.",{"type":135,"ordered":136,"items":292},[293,299,304,309,318],[294,298],{"tag":295,"children":296},"strong",[297],"Single responsibility."," One function per tool, and no second tool that does almost the same thing.",[300,303],{"tag":295,"children":301},[302],"Register for the current state."," Abort the controller when the route or modal changes, so the agent does not see tools that no longer apply.",[305,308],{"tag":295,"children":306},[307],"Accept raw input."," If the user said 11:00 to 15:00, take the string and normalise it in code. Do not make the model do arithmetic.",[310,313,314,317],{"tag":295,"children":311},[312],"Use readable enum values."," \"express\" beats ",{"tag":126,"children":315},[316],"shipping_id = 1",", because the model reads the value, not your database.",[319,322],{"tag":295,"children":320},[321],"Return actionable errors."," Say what to do instead, not what broke internally. A tool that fails should still be usable.",{"type":120,"level":121,"id":100,"text":101},{"type":113,"content":325},[326],"Annotations are the main lever a page has over how a host treats its tools, and all four default to false. That default is the safe one, but it means the safety properties of a tool are exactly as honest as the page that registers it.",{"type":135,"ordered":136,"items":328},[329,334,339,344],[330,333],{"tag":126,"children":331},[332],"readOnlyHint"," the tool reads and changes nothing. Set it on every lookup.",[335,338],{"tag":126,"children":336},[337],"untrustedContentHint"," the return value contains user-generated or externally sourced data and needs delimiting before it reaches the model.",[340,343],{"tag":126,"children":341},[342],"consequentialHint"," the call books, pays, sends or deletes. Clients can use it to force a confirmation prompt.",[345,348],{"tag":126,"children":346},[347],"debugging"," from Chrome 156, marks a developer tool so general-purpose agents can filter it out.",{"type":113,"content":350},[351],"The Chrome security guidance treats indirect prompt injection as unsolved. Models are probabilistic, repeatable attacks against agentic systems exist, and a tool's return value is a channel an attacker can write to. The recommended mitigations are the annotations, the character budgets and origin isolation, which is mitigation rather than a fix. The same page notes that an extension holding host permissions can already drive the page with arbitrary JavaScript, with or without WebMCP.",{"type":250,"variant":353,"title":354,"body":355},"warn","exposedTo is the sharp edge",[356],[357,358,361],"The ",{"tag":126,"children":359},[360],"exposedTo"," option lists secure origins allowed to discover and execute a tool, and the guidance is blunt about it: a read-only tool can still leak user data, and a write tool acts on the user's behalf. Expose only to origins you would hand the credentials to.",{"type":120,"level":121,"id":103,"text":104},{"type":113,"content":364},[365],"The weaknesses come first, because they are the reason this is a watch item rather than a dependency. Support is effectively one engine family. The specification's own status file lists an origin trial in Chrome 149 and Edge 150, experimental support in Brave's Leo chat, support in ChatGPT Desktop, and standards-position entries in Firefox and WebKit with no implementation behind them. On top of that, Chrome's documentation names headless browsing as out of scope, warns that complex interfaces will need a refactor to keep application and interface state in sync, and points out that clients have to visit a site to discover it has tools at all. There is no registry, no manifest and no index.",{"type":261,"head":367,"rows":375},[368,370,371,373],[369],"",[9],[372],"MCP server",[374],"DOM actuation",[376,385,394,403],[377,379,381,383],[378],"Lifecycle",[380],"Tab-bound, gone on navigation",[382],"Persistent daemon",[384],"One request",[386,388,390,392],[387],"Sees",[389],"Live DOM, cookies, session",[391],"Only what you expose",[393],"Whatever the agent scrapes",[395,397,399,401],[396],"Runs your code",[398],"Yes, in the page",[400],"No, server-side only",[402],"No",[404,406,408,410],[405],"Reachable by",[407],"One engine family today",[409],"Any MCP client",[411],"Any browser",{"type":113,"content":413},[414],"The discoverability point deserves emphasis because it breaks the usual business case. A backend MCP server can be found by an agent that never visits the site. A WebMCP tool cannot. The only realistic discovery path today is a user opening the page, which means WebMCP competes on the quality of a session that has already started rather than on reach.",{"type":120,"level":121,"id":106,"text":107},{"type":113,"content":417},[418,419,424],"WebMCP is a well-drawn API for a real problem, and it is drawn better than most teams would have shipped it themselves. It is not yet a dependency. Build the tool layer behind a feature check, keep the human interface as the primary path, and revisit when a second engine ships or when the declarative half stops being Chromium-only. For the mechanics of getting a page agent-ready today, the site's own guide to ",{"tag":420,"to":421,"children":422},"link","\u002Fblog\u002Fwebmcp-agent-ready-website-guide",[423],"making a website agent-ready with declared tools"," covers the implementation detail in depth.",{"type":135,"ordered":426,"items":427},true,[428,430,432,434,436],[429],"Adopt it on product surfaces where a signed-in user and an agent are looking at the same page: booking, checkout, support requests, settings.",[431],"Skip it for read-only content work. A Markdown copy of the page is cheaper and needs no browser at all.",[433],"Skip it if your flows are mostly forms you cannot annotate, or if you cannot keep the interface in sync with the tool path.",[435],"Do not build an MCP server expecting WebMCP to replace it. They are different layers, and the useful architecture uses both.",[437],"Treat the character budgets and the single-responsibility rule as hard constraints on the catalogue, not as suggestions.",{"type":250,"variant":439,"title":440,"body":441},"tip","The cheapest first experiment",[442],[443,444,446],"Pick one existing button handler, wrap it in ",{"tag":126,"children":445},[145]," with the annotations set honestly, and measure whether the agent takes the tool path instead of the click path. That single measurement answers the adoption question faster than any amount of specification reading.",{"type":120,"level":121,"id":109,"text":110},{"type":135,"ordered":426,"items":449},[450,454,457,460,463,466,469,472],[451],{"tag":452,"href":32,"children":453},"a",[31],[455],{"tag":452,"href":35,"children":456},[34],[458],{"tag":452,"href":38,"children":459},[37],[461],{"tag":452,"href":41,"children":462},[40],[464],{"tag":452,"href":44,"children":465},[43],[467],{"tag":452,"href":47,"children":468},[46],[470],{"tag":452,"href":23,"children":471},[49],[473],{"tag":452,"href":52,"children":474},[51],[476,533,580,634],{"slug":477,"published":5,"minutes":478,"category":7,"tags":479,"keywords":484,"about":492,"sources":496,"cover":526,"og":527,"expertise":55,"locales":528,"lang":57,"title":529,"description":530,"coverAlt":531,"url":495,"pricing":532,"kind":480},"browserbase-stagehand",10,[480,481,482,483,13],"Browser automation","Web agents","Headless browsers","Playwright",[485,486,487,488,489,490,491],"browserbase","stagehand","stagehand vs playwright","browserbase pricing","ai web agent framework","headless browser api","browserbase alternatives",[493],{"name":494,"url":495},"Browserbase","https:\u002F\u002Fwww.browserbase.com",[497,500,503,506,509,512,515,518,521,524],{"title":498,"url":499},"Browserbase pricing","https:\u002F\u002Fwww.browserbase.com\u002Fpricing",{"title":501,"url":502},"Browserbase plans and pricing docs","https:\u002F\u002Fdocs.browserbase.com\u002Fguides\u002Fplans-and-pricing",{"title":504,"url":505},"Stagehand documentation","https:\u002F\u002Fdocs.stagehand.dev\u002F",{"title":507,"url":508},"Stagehand quickstart","https:\u002F\u002Fdocs.stagehand.dev\u002Fv4\u002Ffirst-steps\u002Fquickstart",{"title":510,"url":511},"Stagehand v4 announcement","https:\u002F\u002Fwww.browserbase.com\u002Fblog\u002Fstagehand-v4",{"title":513,"url":514},"Stagehand repository","https:\u002F\u002Fgithub.com\u002Fbrowserbase\u002Fstagehand",{"title":516,"url":517},"Browser Use comparison of the two vendors","https:\u002F\u002Fbrowser-use.com\u002Fposts\u002Fbrowser-use-vs-browserbase",{"title":519,"url":520},"Browser Use pricing","https:\u002F\u002Fwww.browser-use.com\u002Fpricing",{"title":522,"url":523},"Skyvern pricing","https:\u002F\u002Fskyvern.com\u002Fpricing",{"title":483,"url":525},"https:\u002F\u002Fplaywright.dev\u002F","\u002Fimages\u002Fblog\u002Fbrowserbase-stagehand\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fbrowserbase-stagehand\u002Fog.jpg",[57,58,59],"Browserbase and Stagehand reviewed: rented Chrome for AI agents","Browserbase rents managed Chrome by the minute and Stagehand adds natural-language steps on top. What it costs, where the meters run and when plain Playwright wins.","Abstract pipeline artwork for the Browserbase and Stagehand review","From $20 per month · OSS library free",{"slug":534,"published":535,"minutes":478,"category":7,"tags":536,"keywords":539,"about":547,"sources":551,"cover":573,"og":574,"expertise":55,"locales":575,"lang":57,"title":576,"description":577,"coverAlt":578,"url":549,"pricing":579,"kind":480},"playwright","2026-05-27",[537,480,13,538],"End-to-end testing","Cross-browser",[534,540,541,542,543,544,545,546],"playwright vs selenium","playwright mcp","browser automation testing","playwright test runner","playwright for ai agents","playwright vs cypress","playwright cloud pricing",[548,550],{"name":483,"url":549},"https:\u002F\u002Fplaywright.dev",{"name":25,"url":26},[552,555,558,561,564,567,570],{"title":553,"url":554},"Playwright documentation: installation","https:\u002F\u002Fplaywright.dev\u002Fdocs\u002Fintro",{"title":556,"url":557},"Playwright MCP introduction","https:\u002F\u002Fplaywright.dev\u002Fmcp\u002Fintroduction",{"title":559,"url":560},"Playwright CLI introduction","https:\u002F\u002Fplaywright.dev\u002Fagent-cli\u002Fintroduction",{"title":562,"url":563},"Playwright Test agents","https:\u002F\u002Fplaywright.dev\u002Fdocs\u002Ftest-agents",{"title":565,"url":566},"npm package metadata for @playwright\u002Ftest","https:\u002F\u002Fregistry.npmjs.org\u002F@playwright\u002Ftest\u002Flatest",{"title":568,"url":569},"Microsoft Learn: Playwright Workspaces free trial","https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fazure\u002Fapp-testing\u002Fplaywright-workspaces\u002Fhow-to-try-playwright-workspaces-free",{"title":571,"url":572},"Azure App Testing pricing","https:\u002F\u002Fazure.microsoft.com\u002Fen-us\u002Fpricing\u002Fdetails\u002Fapp-testing\u002F","\u002Fimages\u002Fblog\u002Fplaywright\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fplaywright\u002Fog.jpg",[57,58,59],"Playwright: one browser API for tests, scripts and agents","Playwright drives Chromium, Firefox and WebKit from one Apache-2.0 API: a test runner, an agent-facing CLI and an MCP server. What it costs and where it falls short.","A Playwright test run: a spec file, a runner fanning out to three browser engines, and an agent reading accessibility snapshots.","Apache-2.0 · cloud paid",{"slug":581,"published":535,"minutes":478,"category":7,"tags":582,"keywords":587,"about":594,"sources":601,"cover":625,"og":626,"expertise":55,"locales":627,"lang":57,"title":628,"description":629,"coverAlt":630,"url":631,"pricing":632,"kind":633},"elevenlabs",[583,584,585,586],"Text to speech","Voice API","Speech to text","Voice cloning",[581,588,589,590,591,592,593],"elevenlabs api pricing","elevenlabs vs openai tts","text to speech api comparison","elevenlabs flash latency","voice cloning api","eleven v4 model",[595,598],{"name":596,"url":597},"ElevenLabs","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FElevenLabs",{"name":599,"url":600},"Speech synthesis","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FSpeech_synthesis",[602,605,608,611,614,616,619,622],{"title":603,"url":604},"ElevenLabs pricing: plans and credits","https:\u002F\u002Felevenlabs.io\u002Fpricing",{"title":606,"url":607},"ElevenAPI pricing: per-product rates","https:\u002F\u002Felevenlabs.io\u002Fpricing\u002Fapi",{"title":609,"url":610},"ElevenLabs documentation: models","https:\u002F\u002Felevenlabs.io\u002Fdocs\u002Fmodels",{"title":612,"url":613},"API reference: create speech","https:\u002F\u002Felevenlabs.io\u002Fdocs\u002Fapi-reference\u002Ftext-to-speech\u002Fconvert",{"title":615,"url":597},"Wikipedia: ElevenLabs",{"title":617,"url":618},"Amazon Polly pricing","https:\u002F\u002Faws.amazon.com\u002Fpolly\u002Fpricing\u002F",{"title":620,"url":621},"OpenAI API pricing","https:\u002F\u002Fdevelopers.openai.com\u002Fapi\u002Fdocs\u002Fpricing",{"title":623,"url":624},"SILMA AI: text to speech price comparison, August 2026","https:\u002F\u002Fsilma.ai\u002Fblog\u002Ftext-to-speech-price-comparison-august-2026","\u002Fimages\u002Fblog\u002Felevenlabs\u002Fcover.webp","\u002Fimages\u002Fblog\u002Felevenlabs\u002Fog.jpg",[57,58,59],"ElevenLabs: speech synthesis as an API","A review of the ElevenLabs audio API: model lineup, latency figures, credit and per-character pricing, tier-gated formats, and where OpenAI and Amazon Polly win.","ElevenLabs cover artwork with speech API pipeline labels","https:\u002F\u002Felevenlabs.io","Free tier · from $5 per month","Voice and audio API",{"slug":635,"published":636,"minutes":478,"category":7,"tags":637,"keywords":643,"about":652,"sources":659,"cover":690,"og":691,"expertise":55,"locales":692,"lang":57,"title":693,"description":694,"coverAlt":695,"url":696,"pricing":697,"kind":698},"replicate","2026-05-22",[638,639,640,641,642],"Model hosting","Serverless GPU","Diffusion","Async jobs","Webhooks",[644,645,646,647,648,649,650,651],"replicate api","replicate vs fal.ai","serverless gpu inference pricing","replicate webhooks","replicate cold start","replicate vs baseten","how to run an open source model in production","replicate prediction api",[653,656],{"name":654,"url":655},"Replicate","https:\u002F\u002Freplicate.com\u002Fdocs",{"name":657,"url":658},"Serverless computing","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FServerless_computing",[660,663,666,669,672,675,678,681,684,687],{"title":661,"url":662},"Replicate pricing","https:\u002F\u002Freplicate.com\u002Fpricing",{"title":664,"url":665},"Replicate docs: About predictions","https:\u002F\u002Freplicate.com\u002Fdocs\u002Ftopics\u002Fpredictions",{"title":667,"url":668},"Replicate docs: Create a prediction","https:\u002F\u002Freplicate.com\u002Fdocs\u002Ftopics\u002Fpredictions\u002Fcreate-a-prediction",{"title":670,"url":671},"Replicate docs: Prediction lifecycle","https:\u002F\u002Freplicate.com\u002Fdocs\u002Ftopics\u002Fpredictions\u002Flifecycle",{"title":673,"url":674},"Replicate docs: Rate limits","https:\u002F\u002Freplicate.com\u002Fdocs\u002Ftopics\u002Fpredictions\u002Frate-limits",{"title":676,"url":677},"Replicate docs: Data retention","https:\u002F\u002Freplicate.com\u002Fdocs\u002Ftopics\u002Fpredictions\u002Fdata-retention",{"title":679,"url":680},"Replicate docs: Verify webhooks","https:\u002F\u002Freplicate.com\u002Fdocs\u002Ftopics\u002Fwebhooks\u002Fverify-webhook",{"title":682,"url":683},"Replicate docs: Official models","https:\u002F\u002Freplicate.com\u002Fdocs\u002Ftopics\u002Fmodels\u002Fofficial-models",{"title":685,"url":686},"fal.ai pricing","https:\u002F\u002Ffal.ai\u002Fpricing",{"title":688,"url":689},"Baseten pricing","https:\u002F\u002Fwww.baseten.co\u002Fpricing\u002F","\u002Fimages\u002Fblog\u002Freplicate\u002Fcover.webp","\u002Fimages\u002Fblog\u002Freplicate\u002Fog.jpg",[57,58,59],"Replicate, reviewed: a model API priced per second, with the sharp edges named","Replicate puts thousands of open models behind one prediction API and bills per second of compute. A review of cold boots, version churn and the one-hour data deletion.","A request moves from starting to processing, then into one of four terminal states: succeeded, failed, canceled or aborted.","https:\u002F\u002Freplicate.com","Pay per second of compute","Model hosting API",1791383548662]