[{"data":1,"prerenderedAt":550},["ShallowReactive",2],{"SiteFooter_cLEacilcm59lTjFJjLY6mXNWLL0ETtzOIiZwIHgDpy0":3,"doc-\u002Fdocs\u002Fconcepts\u002Farchitecture":17,"docs-nav":452,"nav-compare":528,"editor-iargsr":538,"editor-wc16e0":540,"editor-1wxdoku":542,"editor-rdlpee":544,"editor-xdqq2r":546,"editor-1mofl0k":548},["Island",4],{"key":5,"result":6},"SiteFooter_cLEacilcm59lTjFJjLY6mXNWLL0ETtzOIiZwIHgDpy0",{"head":7},{"style":8},[9,11,13,15],{"innerHTML":10},".site-footer[data-v-8bb1d4ae]{border-top:1px solid var(--line);background:var(--chrome);padding:var(--sp-8) var(--gutter) var(--sp-10);gap:var(--sp-6);flex-direction:column;display:flex}.links[data-v-8bb1d4ae]{gap:var(--sp-4);grid-template-columns:repeat(auto-fit,minmax(15rem,1fr));max-width:62rem;display:grid}.links a[data-v-8bb1d4ae]{align-items:flex-start;gap:var(--sp-3);padding:var(--sp-3);border-bottom:1px solid var(--line);border-radius:var(--radius-sm);background:var(--panel);color:var(--ink);border:1px solid var(--line);display:flex}.links a[data-v-8bb1d4ae]:focus-visible,.links a[data-v-8bb1d4ae]:hover{border-color:var(--line-strong)}.links[data-v-8bb1d4ae] .mark,.links[data-v-8bb1d4ae] .rf-mark{width:1.35rem;height:1.35rem;color:var(--dim);flex:none;margin-top:.1rem}.links a[data-v-8bb1d4ae]:hover .mark,.links a[data-v-8bb1d4ae]:hover .rf-mark{color:var(--red)}.links span[data-v-8bb1d4ae]{flex-direction:column;gap:2px;min-width:0;display:flex}.links b[data-v-8bb1d4ae]{font-family:var(--font-display);font-size:.85rem;font-weight:400}.links small[data-v-8bb1d4ae]{color:var(--faint);font-size:.78rem}.colophon[data-v-8bb1d4ae]{color:var(--faint);margin:0;font-size:.75rem}@supports (corner-shape:bevel){.links a[data-v-8bb1d4ae]{corner-shape:bevel}}",{"innerHTML":12},".mark[data-v-cc0d96a5]{vertical-align:-.125em;flex:none;width:1em;height:1em}",{"innerHTML":14},".mark[data-v-26f5673d]{vertical-align:-.125em;flex:none;width:1em;height:1em}",{"innerHTML":16},".rf-mark[data-v-26317b3e]{fill:currentColor;stroke:none;flex:none}",{"id":18,"title":19,"body":20,"description":442,"extension":443,"meta":444,"navigation":445,"order":446,"path":447,"section":448,"seo":449,"stem":450,"__hash__":451},"docs\u002Fdocs\u002Fconcepts\u002Farchitecture.md","How Browser works",{"type":21,"value":22,"toc":433},"minimark",[23,35,38,49,52,57,62,67,90,108,111,140,152,156,193,204,222,226,244,259,266,270,280,310,314,317,327,383,389,392,413,429],[24,25,26,27,34],"p",{},"Browser is a Python library that drives ",[28,29,33],"a",{"href":30,"rel":31},"https:\u002F\u002Fplaywright.dev\u002F",[32],"nofollow","Playwright","\nrunning in Node.js. The two halves talk over gRPC.",[24,36,37],{},"That one sentence explains most of the library's behaviour: why installation has\ntwo moving parts, why there is a second log file, and why a keyword can be fast\neven though it crosses a process boundary.",[39,40,45],"pre",{"className":41,"code":43,"language":44},[42],"language-text","Robot Framework  →  Browser (Python)  →  gRPC  →  Node.js + Playwright  →  browser\n","text",[46,47,43],"code",{"__ignoreMap":48},"",[24,50,51],{},"One Node process drives Chromium, Firefox and WebKit. There is no driver binary\nper browser and no driver version to keep in step with a browser update.",[53,54,56],"h2",{"id":55},"two-ways-to-install","Two ways to install",[58,59],"doc-table",{":head":60,":rows":61},"[\"Method\",\"Node.js needed\",\"Choose it when\"]","[[\"`robotframework-browser-batteries`\",\"No\",\"Fewest moving parts — but you still install browser binaries unless you already have a Chromium-based browser.\"],[\"`robotframework-browser` + `rfbrowser init`\",\"Yes\",\"Your OS or CPU is not covered, or you need extra Node dependencies.\"]]",[63,64,66],"h3",{"id":65},"without-nodejs-the-fewest-moving-parts","Without Node.js — the fewest moving parts",[39,68,72],{"className":69,"code":70,"language":71,"meta":48,"style":48},"language-bash shiki shiki-themes github-light github-dark","pip install robotframework-browser-batteries\n","bash",[46,73,74],{"__ignoreMap":48},[75,76,79,83,87],"span",{"class":77,"line":78},"line",1,[75,80,82],{"class":81},"sScJk","pip",[75,84,86],{"class":85},"sZZnC"," install",[75,88,89],{"class":85}," robotframework-browser-batteries\n",[24,91,92,95,96,99,100,103,104,107],{},[46,93,94],{},"robotframework-browser-batteries"," is a platform-specific Python wheel carrying\nan unmodified official Node.js runtime, the gRPC wrapper and its production Node\ndependencies, installed into ",[46,97,98],{},"site-packages\u002FBrowserBatteries\u002Fbin\u002F",". It is not a\nsingle binary — it is a real ",[46,101,102],{},"node"," plus a ",[46,105,106],{},"node_modules",".",[24,109,110],{},"Then, if you need browser binaries — you may not, if you already have a\nChromium-based browser and only intend to use that:",[39,112,114],{"className":69,"code":113,"language":71,"meta":48,"style":48},"rfbrowser install            # all three engines\nrfbrowser install firefox    # just one\n",[46,115,116,127],{"__ignoreMap":48},[75,117,118,121,123],{"class":77,"line":78},[75,119,120],{"class":81},"rfbrowser",[75,122,86],{"class":85},[75,124,126],{"class":125},"sJ8bj","            # all three engines\n",[75,128,130,132,134,137],{"class":77,"line":129},2,[75,131,120],{"class":81},[75,133,86],{"class":85},[75,135,136],{"class":85}," firefox",[75,138,139],{"class":125},"    # just one\n",[24,141,142,143,147,148,151],{},"The catch is coverage. Wheels exist for Linux x64 and arm64, Windows x64, and\nmacOS x64 and arm64 — and they need ",[144,145,146],"strong",{},"glibc 2.28 or newer"," (Debian 10, RHEL 8,\nUbuntu 20.04) and ",[144,149,150],{},"macOS 13.5 or newer"," (the wheel tag can only say 13.0, so on 13.0–13.4\npip installs it and the bundled Node.js will not start). There is no musl wheel and none for\nWindows on arm. On anything outside that, pip finds no wheel and you want the\nNode.js route. It also carries only what Browser itself needs, so extra Node\ndependencies are the other method's job.",[63,153,155],{"id":154},"with-nodejs","With Node.js",[39,157,159],{"className":69,"code":158,"language":71,"meta":48,"style":48},"pip install robotframework-browser\nrfbrowser init               # mandatory — the library does not work without it\nrfbrowser init chromium      # or just one engine\n",[46,160,161,170,180],{"__ignoreMap":48},[75,162,163,165,167],{"class":77,"line":78},[75,164,82],{"class":81},[75,166,86],{"class":85},[75,168,169],{"class":85}," robotframework-browser\n",[75,171,172,174,177],{"class":77,"line":129},[75,173,120],{"class":81},[75,175,176],{"class":85}," init",[75,178,179],{"class":125},"               # mandatory — the library does not work without it\n",[75,181,183,185,187,190],{"class":77,"line":182},3,[75,184,120],{"class":81},[75,186,176],{"class":85},[75,188,189],{"class":85}," chromium",[75,191,192],{"class":125},"      # or just one engine\n",[24,194,195,196,199,200,203],{},"Slower to set up, but works anywhere Python and Node.js do, and leaves you a\nnormal Node toolchain — ",[46,197,198],{},"npm"," and ",[46,201,202],{},"npx"," — on the machine.",[24,205,206,207,210,211,214,215,218,219,221],{},"Do not install extra Node packages into ",[46,208,209],{},"Browser\u002Fwrapper"," by hand: ",[46,212,213],{},"rfbrowser init"," runs ",[46,216,217],{},"npm ci"," there, which deletes ",[46,220,106],{}," and reinstalls exactly\nthe production dependencies from the shipped lockfile, so anything you added\ndisappears on the next init or\nupgrade.",[53,223,225],{"id":224},"where-things-end-up","Where things end up",[24,227,228,229,232,233,236,237,239,240,243],{},"Everything installs into the Python environment, for example\n",[46,230,231],{},".venv\u002Flib\u002Fpython3.14\u002Fsite-packages\u002FBrowser\u002F",". Node dependencies go to\n",[46,234,235],{},"Browser\u002Fwrapper\u002Fnode_modules"," with ",[46,238,213],{},", or ship inside\n",[46,241,242],{},"BrowserBatteries\u002Fbin\u002Fwrapper\u002Fnode_modules"," with batteries.",[24,245,246,247,250,251,254,255,258],{},"Browser binaries are Playwright's, but the location is not Playwright's default:\nwhen ",[46,248,249],{},"PLAYWRIGHT_BROWSERS_PATH"," is unset, Browser sets it to ",[46,252,253],{},"0",", which puts\nthem in ",[46,256,257],{},"Browser\u002Fwrapper\u002Fnode_modules\u002Fplaywright-core\u002F.local-browsers"," — inside\nthe Python environment rather than in Playwright's shared user cache. Setting the\nvariable yourself moves them.",[24,260,261,262,265],{},"Installation logs to the console and to ",[46,263,264],{},"site-packages\u002FBrowser\u002Frfbrowser.log",",\nwhich rotates at about 2 MB and keeps ten previous files. If that directory is\nnot writable, the log goes to the working directory instead.",[53,267,269],{"id":268},"managing-environments","Managing environments",[271,272,273],"doc-note",{},[24,274,275,276,279],{},"The single rule worth stating: ",[144,277,278],{},"never install into the system Python."," You\nwill need to test against more than one Python version sooner than you expect,\nand an unpicked system install is painful to undo.",[24,281,282,283,286,287,290,291,294,295,298,299,302,303,298,306,309],{},"Use ",[46,284,285],{},"uv",", ",[46,288,289],{},"pyenv"," or plain ",[46,292,293],{},"venv"," — all are fine, and which suits you depends on\nyour organisation more than on Browser. For Node.js, use a version manager too:\n",[46,296,297],{},"n"," or ",[46,300,301],{},"nvm"," on Linux and macOS, ",[46,304,305],{},"nvm-windows",[46,307,308],{},"nodist"," on Windows.",[53,311,313],{"id":312},"browser-binaries-in-ci","Browser binaries in CI",[24,315,316],{},"Downloading browser binaries on every CI run is slow and, where several\nenvironments share a machine, wasteful — because the default puts a copy inside\neach installation.",[24,318,319,320,322,323,326],{},"On the Node.js route, install them once outside the library. Run ",[46,321,202],{}," from the\nlibrary's own wrapper directory so the pinned Playwright is used — a bare ",[46,324,325],{},"npx playwright install"," fetches whatever npm resolves, and browser builds are\nversion-specific:",[39,328,330],{"className":69,"code":329,"language":71,"meta":48,"style":48},"rfbrowser init --skip-browsers\ncd \"$(python -c 'import Browser, pathlib; print(pathlib.Path(Browser.__file__).parent \u002F \"wrapper\")')\"\nPLAYWRIGHT_BROWSERS_PATH=$HOME\u002Fpw-browsers npx playwright install\n",[46,331,332,342,359],{"__ignoreMap":48},[75,333,334,336,338],{"class":77,"line":78},[75,335,120],{"class":81},[75,337,176],{"class":85},[75,339,341],{"class":340},"sj4cs"," --skip-browsers\n",[75,343,344,347,350,353,356],{"class":77,"line":129},[75,345,346],{"class":340},"cd",[75,348,349],{"class":85}," \"$(",[75,351,352],{"class":81},"python",[75,354,355],{"class":340}," -c",[75,357,358],{"class":85}," 'import Browser, pathlib; print(pathlib.Path(Browser.__file__).parent \u002F \"wrapper\")')\"\n",[75,360,361,364,368,371,374,377,380],{"class":77,"line":182},[75,362,249],{"class":363},"sVt8B",[75,365,367],{"class":366},"szBVR","=",[75,369,370],{"class":363},"$HOME",[75,372,373],{"class":85},"\u002Fpw-browsers",[75,375,376],{"class":81}," npx",[75,378,379],{"class":85}," playwright",[75,381,382],{"class":85}," install\n",[24,384,385,386,107],{},"With batteries there is no npm or npx; the equivalent is\n",[46,387,388],{},"PLAYWRIGHT_BROWSERS_PATH=$HOME\u002Fpw-browsers rfbrowser install",[24,390,391],{},"Then set the same variable before running the tests:",[39,393,395],{"className":69,"code":394,"language":71,"meta":48,"style":48},"PLAYWRIGHT_BROWSERS_PATH=$HOME\u002Fpw-browsers robot tests\u002F\n",[46,396,397],{"__ignoreMap":48},[75,398,399,401,403,405,407,410],{"class":77,"line":78},[75,400,249],{"class":363},[75,402,367],{"class":366},[75,404,370],{"class":363},[75,406,373],{"class":85},[75,408,409],{"class":81}," robot",[75,411,412],{"class":85}," tests\u002F\n",[271,414,416],{"kind":415},"warning",[24,417,418,420,421,424,425,428],{},[46,419,249],{}," must be set for the ",[46,422,423],{},"robot"," command too, not only for\nthe install step. If it is set during install and not during the run, Playwright\nlooks in the library's own ",[46,426,427],{},".local-browsers"," directory, finds it empty, and\nreports that the browser executable does not exist.",[430,431,432],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}",{"title":48,"searchDepth":129,"depth":129,"links":434},[435,439,440,441],{"id":55,"depth":129,"text":56,"children":436},[437,438],{"id":65,"depth":182,"text":66},{"id":154,"depth":182,"text":155},{"id":224,"depth":129,"text":225},{"id":268,"depth":129,"text":269},{"id":312,"depth":129,"text":313},"Python, a Node process and Playwright — what runs where, and which installation to choose.","md",{},true,5,"\u002Fdocs\u002Fconcepts\u002Farchitecture","concepts",{"title":19,"description":442},"docs\u002Fconcepts\u002Farchitecture","xmTgqsmNgbVvwX-42_W5otsGBXYEgfwbZJdDf-jaHQI",[453,454,458,462,467,471,476,481,485,489,493,498,502,506,511,515,519,523],{"path":447,"title":19,"description":442,"section":448,"order":446},{"path":455,"title":456,"description":457,"section":448,"order":182},"\u002Fdocs\u002Fconcepts\u002Fassertions","Assertions","Almost every getter can assert, every assertion retries, and each return type allows different operators. The complete AssertionEngine reference.",{"path":459,"title":460,"description":461,"section":448,"order":78},"\u002Fdocs\u002Fconcepts\u002Fbrowser-context-page","Browser, context and page","The three layers Playwright is built on — and why a new context is the cheapest clean slate you will ever get.",{"path":463,"title":464,"description":465,"section":448,"order":466},"\u002Fdocs\u002Fconcepts\u002Flogging","Logging and debugging","Four places Browser tells you what happened — log.html, the Playwright log, traces and coverage.",6,{"path":468,"title":469,"description":470,"section":448,"order":129},"\u002Fdocs\u002Fconcepts\u002Fselectors","Finding elements","Which selector strategy to reach for, why the order matters, and how to chain across iframes and shadow DOM.",{"path":472,"title":473,"description":474,"section":448,"order":475},"\u002Fdocs\u002Fconcepts\u002Fwaiting","Waiting and promises","Most waiting is already done for you. This is the rest of it — Wait For Condition, and how to run keywords in parallel with Promise To.",4,{"path":477,"title":478,"description":479,"section":480,"order":129},"\u002Fdocs\u002Fextending\u002Fjavascript-basics","Just enough JavaScript","The JavaScript you need to write extensions and Evaluate JavaScript, for people who write Python.","extending",{"path":482,"title":483,"description":484,"section":480,"order":182},"\u002Fdocs\u002Fextending\u002Fjavascript-extensions","JavaScript extensions","Add keywords that run on the Node side with full Playwright access — and attach a debugger to them.",{"path":486,"title":487,"description":488,"section":480,"order":78},"\u002Fdocs\u002Fextending\u002Fpython-plugins","Python plugins","Add or replace keywords from Python, with access to the library's own API and to the Node side.",{"path":490,"title":491,"description":492,"section":480,"order":475},"\u002Fdocs\u002Fextending\u002Ftranslations","Translating keywords","Using a translation package to get keyword names and documentation in your language, and writing one for a language nobody has covered yet.",{"path":494,"title":495,"description":496,"section":497,"order":129},"\u002Fdocs\u002Fmobile\u002Fdevices","Emulating a device","Device descriptors, what the six or seven properties they set actually change, and the one that emulation cannot give you.","mobile",{"path":499,"title":500,"description":501,"section":497,"order":78},"\u002Fdocs\u002Fmobile\u002Fresponsive","Testing responsive pages","Why a browser at a phone-sized viewport tests responsiveness properly, what emulation cannot tell you, and where real devices actually belong.",{"path":503,"title":504,"description":505,"section":497,"order":182},"\u002Fdocs\u002Fmobile\u002Ftouch","Touch, permissions and location","Tap and why it needs hasTouch, granting camera or notifications without a dialog, faking where the user is, and the gestures Browser has no keyword for.",{"path":507,"title":508,"description":509,"section":510,"order":182},"\u002Fdocs\u002Foperations\u002Fdocker","Running in Docker","The published Browser image, the four docker run flags that matter, and why running as root breaks Chromium.","operations",{"path":512,"title":513,"description":514,"section":510,"order":475},"\u002Fdocs\u002Foperations\u002Fdocker-images","Building your own image","Extending the published image with your dependencies, the version lock between Browser and Playwright, and using it as a CI job container.",{"path":516,"title":517,"description":518,"section":510,"order":129},"\u002Fdocs\u002Foperations\u002Fenvironment-variables","Environment variables","The variables that change how Browser behaves, which of them are safe in production, and the import parameters that should usually be preferred.",{"path":520,"title":521,"description":522,"section":510,"order":78},"\u002Fdocs\u002Foperations\u002Fnode-process","The Node process","Browser starts a Node process to talk to Playwright. What that costs, how to share one across parallel runs, and how to pass it Node flags.",{"path":524,"title":525,"description":526,"section":527,"order":78},"\u002Fdocs\u002Fstart\u002Fgetting-started","Getting started","Install Browser, write a first test, and run it.","start",[529,532,535],{"to":530,"label":531},"\u002Fwhy\u002Fvs-cypress","vs Cypress",{"to":533,"label":534},"\u002Fwhy\u002Fvs-playwright","vs Playwright Test",{"to":536,"label":537},"\u002Fwhy\u002Fvs-seleniumlibrary","vs SeleniumLibrary",[539],"\u003Cspan class=\"line\">\u003Cspan>Robot Framework  →  Browser (Python)  →  gRPC  →  Node.js + Playwright  →  browser\u003C\u002Fspan>\u003C\u002Fspan>",[541],"\u003Cspan class=\"line\">\u003Cspan style=\"color:#2BD9CC\">pip\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\"> install\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\"> robotframework-browser-batteries\u003C\u002Fspan>\u003C\u002Fspan>",[543],"\u003Cspan class=\"line\">\u003Cspan style=\"color:#2BD9CC\">rfbrowser\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\"> install\u003C\u002Fspan>\u003Cspan style=\"color:#96A2A8;font-style:italic\">            # all three engines\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan style=\"color:#2BD9CC\">rfbrowser\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\"> install\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\"> firefox\u003C\u002Fspan>\u003Cspan style=\"color:#96A2A8;font-style:italic\">    # just one\u003C\u002Fspan>\u003C\u002Fspan>",[545],"\u003Cspan class=\"line\">\u003Cspan style=\"color:#2BD9CC\">pip\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\"> install\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\"> robotframework-browser\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan style=\"color:#2BD9CC\">rfbrowser\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\"> init\u003C\u002Fspan>\u003Cspan style=\"color:#96A2A8;font-style:italic\">               # mandatory — the library does not work without it\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan style=\"color:#2BD9CC\">rfbrowser\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\"> init\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\"> chromium\u003C\u002Fspan>\u003Cspan style=\"color:#96A2A8;font-style:italic\">      # or just one engine\u003C\u002Fspan>\u003C\u002Fspan>",[547],"\u003Cspan class=\"line\">\u003Cspan style=\"color:#2BD9CC\">rfbrowser\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\"> init\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\"> --skip-browsers\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan style=\"color:#2BD9CC\">cd\u003C\u002Fspan>\u003Cspan style=\"color:#A9B4BA\"> \"$(\u003C\u002Fspan>\u003Cspan style=\"color:#2BD9CC\">python\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\"> -c \u003C\u002Fspan>\u003Cspan style=\"color:#A9B4BA\">'\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\">import Browser, pathlib; print(pathlib.Path(Browser.__file__).parent \u002F \"wrapper\")\u003C\u002Fspan>\u003Cspan style=\"color:#A9B4BA\">')\"\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan style=\"color:#FFB86B\">PLAYWRIGHT_BROWSERS_PATH\u003C\u002Fspan>\u003Cspan style=\"color:#FF6B5E\">=\u003C\u002Fspan>\u003Cspan style=\"color:#FFB86B\">$HOME\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\">\u002Fpw-browsers\u003C\u002Fspan>\u003Cspan style=\"color:#2BD9CC\"> npx\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\"> playwright\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\"> install\u003C\u002Fspan>\u003C\u002Fspan>",[549],"\u003Cspan class=\"line\">\u003Cspan style=\"color:#FFB86B\">PLAYWRIGHT_BROWSERS_PATH\u003C\u002Fspan>\u003Cspan style=\"color:#FF6B5E\">=\u003C\u002Fspan>\u003Cspan style=\"color:#FFB86B\">$HOME\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\">\u002Fpw-browsers\u003C\u002Fspan>\u003Cspan style=\"color:#2BD9CC\"> robot\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\"> tests\u002F\u003C\u002Fspan>\u003C\u002Fspan>",1786734138293]