[{"data":1,"prerenderedAt":406},["ShallowReactive",2],{"SiteFooter_cLEacilcm59lTjFJjLY6mXNWLL0ETtzOIiZwIHgDpy0":3,"doc-\u002Fdocs\u002Fstart\u002Fgetting-started":17,"docs-nav":322,"nav-compare":392,"editor-9za70s":402,"editor-zwggj9":404},["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":314,"extension":315,"meta":316,"navigation":167,"order":140,"path":317,"section":318,"seo":319,"stem":320,"__hash__":321},"docs\u002Fdocs\u002Fstart\u002Fgetting-started.md","Getting started",{"type":21,"value":22,"toc":307},"minimark",[23,27,32,60,83,92,96,100,105,109,116,127,143,205,208,211,221,237,241,244,258,262,269,292,303],[24,25,26],"p",{},"Install the library and its browser binaries, write one test, run it.",[28,29,31],"h2",{"id":30},"before-you-start","Before you start",[24,33,34,35,39,40,43,44,48,49,39,52,55,56],{},"You need ",[36,37,38],"strong",{},"Python 3.10 or newer"," and ",[36,41,42],{},"Node.js with npm on your PATH"," —\n",[45,46,47],"code",{},"rfbrowser init"," runs ",[45,50,51],{},"npm ci --omit=dev",[45,53,54],{},"npx playwright install","\nunderneath, and if npm is not on the PATH it stops with ",[57,58,59],"em",{},"Couldn't execute npm.\nPlease ensure you have node.js and npm installed and in PATH.",[24,61,62,63,66,67,70,71,74,75,78,79,82],{},"Do this in a virtual environment — ",[45,64,65],{},"uv",", ",[45,68,69],{},"venv"," or ",[45,72,73],{},"pyenv",", whichever your team\nuses. ",[36,76,77],{},"Never install into the system Python:"," the install writes into\n",[45,80,81],{},"site-packages",", so it needs root there and is painful to unpick afterwards.",[24,84,85,86,91],{},"There is a second route that needs no Node.js at all, and it is the simpler one\nif you have no particular reason to want Node on the machine — see\n",[87,88,90],"a",{"href":89},"\u002Fdocs\u002Fconcepts\u002Farchitecture","how Browser works"," once you are running.",[28,93,95],{"id":94},"install","Install",[97,98],"terminal-block",{":sessions":99},"[{\"shell\":\"bash\",\"steps\":[{\"command\":\"pip install robotframework-browser\",\"output\":[\"Successfully installed robotframework-browser-%%browser%%\"]},{\"command\":\"rfbrowser init\",\"output\":[\"Installing node dependencies...\",\"Installing browser binaries to 0\",\"rfbrowser init completed\"]}]},{\"shell\":\"powershell\",\"steps\":[{\"command\":\"py -m pip install robotframework-browser\",\"output\":[\"Successfully installed robotframework-browser-%%browser%%\"]},{\"command\":\"rfbrowser init\",\"output\":[\"Installing node dependencies...\",\"Installing browser binaries to 0\",\"rfbrowser init completed\"]}]}]",[24,101,102,104],{},[45,103,47],{}," downloads three browser engines, so it is the slow part and it\nneeds a few hundred megabytes. You only do it once per environment.",[28,106,108],{"id":107},"your-first-test","Your first test",[24,110,111,112,115],{},"The assertion is part of the keyword — ",[45,113,114],{},"Get Title"," both reads and checks.",[24,117,118,119,122,123,126],{},"The browser runs ",[36,120,121],{},"headless"," by default, so this prints a result without\nanything appearing on screen. To watch it, open the browser yourself above\n",[45,124,125],{},"New Page",":",[128,129,134],"pre",{"className":130,"code":131,"language":132,"meta":133,"style":133},"language-robot-repl shiki shiki-themes github-light github-dark","New Browser    chromium    headless=False\n","robot-repl","",[45,135,136],{"__ignoreMap":133},[137,138,141],"span",{"class":139,"line":140},"line",1,[137,142,131],{},[128,144,149],{"className":145,"code":146,"filename":147,"language":148,"meta":133,"style":133},"language-robot shiki shiki-themes github-light github-dark","*** Settings ***\nLibrary    Browser\n\n*** Test Cases ***\nOpen The Keyword Reference\n    New Page     https:\u002F\u002Frobotframework-browser.org\n    Get Title    *=    Robot Framework Browser\n    Click        nav[aria-label=\"Main\"] >> text=\"Keywords\"\n    Get Title    *=    Keyword reference\n","first.robot","robot",[45,150,151,156,162,169,175,181,187,193,199],{"__ignoreMap":133},[137,152,153],{"class":139,"line":140},[137,154,155],{},"*** Settings ***\n",[137,157,159],{"class":139,"line":158},2,[137,160,161],{},"Library    Browser\n",[137,163,165],{"class":139,"line":164},3,[137,166,168],{"emptyLinePlaceholder":167},true,"\n",[137,170,172],{"class":139,"line":171},4,[137,173,174],{},"*** Test Cases ***\n",[137,176,178],{"class":139,"line":177},5,[137,179,180],{},"Open The Keyword Reference\n",[137,182,184],{"class":139,"line":183},6,[137,185,186],{},"    New Page     https:\u002F\u002Frobotframework-browser.org\n",[137,188,190],{"class":139,"line":189},7,[137,191,192],{},"    Get Title    *=    Robot Framework Browser\n",[137,194,196],{"class":139,"line":195},8,[137,197,198],{},"    Click        nav[aria-label=\"Main\"] >> text=\"Keywords\"\n",[137,200,202],{"class":139,"line":201},9,[137,203,204],{},"    Get Title    *=    Keyword reference\n",[24,206,207],{},"It drives this site, so you can run it right now without an application of your\nown — and the pages it touches are the ones you are reading.",[24,209,210],{},"Two things are doing work in that selector, and both are worth copying.",[24,212,213,216,217,220],{},[45,214,215],{},">>"," chains: everything left of it narrows the search, so ",[45,218,219],{},"text=\"Keywords\""," is\nlooked for only inside the main navigation. The page has a second link with that\nexact text — in the row of figures on the landing page — and Playwright is\nstrict: a selector matching more than one element is an error, not a silent\nfirst-match.",[24,222,223,224,227,228,231,232,236],{},"The quotes make it an ",[57,225,226],{},"exact"," match. Without them, ",[45,229,230],{},"text=Keywords"," is a\ncase-insensitive substring, which would also find \"keywords\" inside a sentence.\nSee ",[87,233,235],{"href":234},"\u002Fdocs\u002Fconcepts\u002Fselectors","selectors",".",[28,238,240],{"id":239},"run-it","Run it",[97,242],{":sessions":243},"[{\"shell\":\"bash\",\"steps\":[{\"command\":\"robot first.robot\",\"output\":[\"Open The Keyword Reference                                            | PASS |\",\"1 test, 1 passed, 0 failed\"]}]}]",[24,245,246,247,250,251,253,254,257],{},"Robot Framework writes ",[45,248,249],{},"log.html"," into the directory you ran ",[45,252,148],{}," from — not\nnext to the test file — unless you pass ",[45,255,256],{},"--outputdir",". Open it — every keyword,\nits arguments and its result are in there, and it is the first place to look\nwhen something fails.",[28,259,261],{"id":260},"what-is-not-in-that-test","What is not in that test",[24,263,264,265,268],{},"No ",[45,266,267],{},"Sleep",", and no wait keyword before anything. Two different mechanisms are\ndoing that work:",[270,271,272,283],"ul",{},[273,274,275,278,279,282],"li",{},[36,276,277],{},"Action keywords"," like ",[45,280,281],{},"Click"," wait for the element to be actionable —\nattached, visible, stable and able to receive the click — before acting.",[273,284,285,288,289,291],{},[36,286,287],{},"Assertions"," like the ",[45,290,114],{}," line above re-read the value until it\nmatches or the retry window expires.",[24,293,294,295,298,299,236],{},"So a keyword with an assertion operator is itself the wait. A getter ",[57,296,297],{},"without","\none reads once and returns. That distinction is the whole of\n",[87,300,302],{"href":301},"\u002Fdocs\u002Fconcepts\u002Fassertions","assertions",[304,305,306],"style",{},"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);}",{"title":133,"searchDepth":158,"depth":158,"links":308},[309,310,311,312,313],{"id":30,"depth":158,"text":31},{"id":94,"depth":158,"text":95},{"id":107,"depth":158,"text":108},{"id":239,"depth":158,"text":240},{"id":260,"depth":158,"text":261},"Install Browser, write a first test, and run it.","md",{},"\u002Fdocs\u002Fstart\u002Fgetting-started","start",{"title":19,"description":314},"docs\u002Fstart\u002Fgetting-started","qQSwz4dZ-V0XCkjg_HpOUmX4tiamfs-kWjxw33eRXgg",[323,327,329,333,337,340,344,349,353,357,361,366,370,374,379,383,387,391],{"path":89,"title":324,"description":325,"section":326,"order":177},"How Browser works","Python, a Node process and Playwright — what runs where, and which installation to choose.","concepts",{"path":301,"title":287,"description":328,"section":326,"order":164},"Almost every getter can assert, every assertion retries, and each return type allows different operators. The complete AssertionEngine reference.",{"path":330,"title":331,"description":332,"section":326,"order":140},"\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":334,"title":335,"description":336,"section":326,"order":183},"\u002Fdocs\u002Fconcepts\u002Flogging","Logging and debugging","Four places Browser tells you what happened — log.html, the Playwright log, traces and coverage.",{"path":234,"title":338,"description":339,"section":326,"order":158},"Finding elements","Which selector strategy to reach for, why the order matters, and how to chain across iframes and shadow DOM.",{"path":341,"title":342,"description":343,"section":326,"order":171},"\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.",{"path":345,"title":346,"description":347,"section":348,"order":158},"\u002Fdocs\u002Fextending\u002Fjavascript-basics","Just enough JavaScript","The JavaScript you need to write extensions and Evaluate JavaScript, for people who write Python.","extending",{"path":350,"title":351,"description":352,"section":348,"order":164},"\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":354,"title":355,"description":356,"section":348,"order":140},"\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":358,"title":359,"description":360,"section":348,"order":171},"\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":362,"title":363,"description":364,"section":365,"order":158},"\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":367,"title":368,"description":369,"section":365,"order":140},"\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":371,"title":372,"description":373,"section":365,"order":164},"\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":375,"title":376,"description":377,"section":378,"order":164},"\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":380,"title":381,"description":382,"section":378,"order":171},"\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":384,"title":385,"description":386,"section":378,"order":158},"\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":388,"title":389,"description":390,"section":378,"order":140},"\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":317,"title":19,"description":314,"section":318,"order":140},[393,396,399],{"to":394,"label":395},"\u002Fwhy\u002Fvs-cypress","vs Cypress",{"to":397,"label":398},"\u002Fwhy\u002Fvs-playwright","vs Playwright Test",{"to":400,"label":401},"\u002Fwhy\u002Fvs-seleniumlibrary","vs SeleniumLibrary",[403],"\u003Cspan class=\"line\">\u003Cspan style=\"color:#2BD9CC\">New Browser\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\">    chromium    headless=False\u003C\u002Fspan>\u003C\u002Fspan>",[405],"\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF6B5E;font-weight:bold\">*** Settings ***\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan style=\"color:#C9A6E9\">Library\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\">    Browser\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF6B5E;font-weight:bold\">*** Test Cases ***\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan style=\"color:#2BD9CC\">Open The Keyword Reference\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan style=\"color:#2BD9CC\">    New Page\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\">     https:\u002F\u002Frobotframework-browser.org\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan style=\"color:#2BD9CC\">    Get Title\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\">    *=\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\">    Robot Framework Browser\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan style=\"color:#2BD9CC\">    Click\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\">        nav[aria-label=\"Main\"] >> text=\"Keywords\"\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan style=\"color:#2BD9CC\">    Get Title\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\">    *=\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\">    Keyword reference\u003C\u002Fspan>\u003C\u002Fspan>",1786734136991]