"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[64885],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>d});var a=n(67294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function l(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var s=a.createContext({}),p=function(e){var t=a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},c=function(e){var t=p(e.components);return a.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},m=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,s=e.parentName,c=i(e,["components","mdxType","originalType","parentName"]),m=p(n),d=r,h=m["".concat(s,".").concat(d)]||m[d]||u[d]||o;return n?a.createElement(h,l(l({ref:t},c),{},{components:n})):a.createElement(h,l({ref:t},c))}));function d(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,l=new Array(o);l[0]=m;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i.mdxType="string"==typeof e?e:r,l[1]=i;for(var p=2;p{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>i,default:()=>m,frontMatter:()=>l,metadata:()=>s,toc:()=>c});n(67294);var a=n(3905);function r(){return r=Object.assign||function(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}const l={},i="Query Selectors",s={unversionedId:"guides/query-selectors",id:"guides/query-selectors",title:"Query Selectors",description:"Queries are the primary mechanism for interacting with the DOM on your site. For example, a typical workflow goes like:",source:"@site/../docs/guides/query-selectors.md",sourceDirName:"guides",slug:"/guides/query-selectors",permalink:"/next/guides/query-selectors",draft:!1,tags:[],version:"current",frontMatter:{},sidebar:"docs",previous:{title:"Configuration",permalink:"/next/guides/configuration"},next:{title:"Evaluate JavaScript",permalink:"/next/guides/evaluate-javascript"}},p={},c=[{value:"P Selectors",id:"p-selectors",level:2},{value:">>> and >>>> combinators",id:"-and--combinators",level:3},{value:"Example",id:"example",level:4},{value:"P-elements",id:"p-elements",level:3},{value:"Text selectors (-p-text)",id:"text-selectors--p-text",level:4},{value:"Example",id:"example-1",level:5},{value:"XPath selectors (-p-xpath)",id:"xpath-selectors--p-xpath",level:4},{value:"Example",id:"example-2",level:5},{value:"ARIA selectors (-p-aria)",id:"aria-selectors--p-aria",level:4},{value:"Example",id:"example-3",level:5},{value:"Custom selectors",id:"custom-selectors",level:3},{value:"Example",id:"example-4",level:4}],u={toc:c};function m(e){var{components:t}=e,n=o(e,["components"]);return(0,a.kt)("wrapper",r({},u,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",r({},{id:"query-selectors"}),"Query Selectors"),(0,a.kt)("p",null,"Queries are the primary mechanism for interacting with the DOM on your site. For example, a typical workflow goes like:"),(0,a.kt)("pre",null,(0,a.kt)("code",r({parentName:"pre"},{className:"language-ts"}),"// Import puppeteer\nimport puppeteer from 'puppeteer';\n\n(async () => {\n // Launch the browser\n const browser = await puppeteer.launch();\n\n // Create a page\n const page = await browser.newPage();\n\n // Go to your site\n await page.goto('YOUR_SITE');\n\n // Query for an element handle.\n const element = await page.waitForSelector('div > .class-name');\n\n // Do something with element...\n await element.click(); // Just an example.\n\n // Dispose of handle\n await element.dispose();\n\n // Close browser.\n await browser.close();\n})();\n")),(0,a.kt)("h2",r({},{id:"p-selectors"}),(0,a.kt)("inlineCode",{parentName:"h2"},"P")," Selectors"),(0,a.kt)("p",null,"Puppeteer uses a superset of the CSS selector syntax for querying. We call this syntax ",(0,a.kt)("em",{parentName:"p"},"P selectors")," and it's supercharged with extra capabilities such as deep combinators and text selection."),(0,a.kt)("admonition",r({},{type:"caution"}),(0,a.kt)("p",{parentName:"admonition"},"Although P selectors look like real CSS selectors (we intentionally designed it this way), they should not be used for actually CSS styling. They are designed only for Puppeteer.")),(0,a.kt)("admonition",r({},{type:"note"}),(0,a.kt)("p",{parentName:"admonition"},'P selectors only work on the first "depth" of selectors; for example, ',(0,a.kt)("inlineCode",{parentName:"p"},":is(div >>> a)")," will not work.")),(0,a.kt)("h3",r({},{id:"-and--combinators"}),(0,a.kt)("inlineCode",{parentName:"h3"},">>>")," and ",(0,a.kt)("inlineCode",{parentName:"h3"},">>>>")," combinators"),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},">>>")," and ",(0,a.kt)("inlineCode",{parentName:"p"},">>>>")," are called ",(0,a.kt)("em",{parentName:"p"},"deep descendent")," and ",(0,a.kt)("em",{parentName:"p"},"deep")," combinators respectively. Both combinators have the effect of going into shadow hosts with ",(0,a.kt)("inlineCode",{parentName:"p"},">>>")," going into every shadow host under a node and ",(0,a.kt)("inlineCode",{parentName:"p"},">>>>")," going into the immediate one (if the node is a shadow host; otherwise, it's a no-op)."),(0,a.kt)("admonition",r({},{type:"note"}),(0,a.kt)("p",{parentName:"admonition"},"A common question is when should ",(0,a.kt)("inlineCode",{parentName:"p"},">>>>")," be chosen over ",(0,a.kt)("inlineCode",{parentName:"p"},">>>")," considering the flexibility of ",(0,a.kt)("inlineCode",{parentName:"p"},">>>"),". A similar question can be asked about ",(0,a.kt)("inlineCode",{parentName:"p"},">")," and a space; choose ",(0,a.kt)("inlineCode",{parentName:"p"},">")," if you do not need to query all elements under a given node and a space otherwise. This answer extends to ",(0,a.kt)("inlineCode",{parentName:"p"},">>>>")," (",(0,a.kt)("inlineCode",{parentName:"p"},">"),") and ",(0,a.kt)("inlineCode",{parentName:"p"},">>>")," (space) naturally.")),(0,a.kt)("h4",r({},{id:"example"}),"Example"),(0,a.kt)("p",null,"Suppose we have the markup"),(0,a.kt)("pre",null,(0,a.kt)("code",r({parentName:"pre"},{className:"language-html"}),'\n \n \n \n \n \n

Light content

\n
\n
\n
\n')),(0,a.kt)("p",null,"Then ",(0,a.kt)("inlineCode",{parentName:"p"},"custom-element >>> h2")," will return ",(0,a.kt)("inlineCode",{parentName:"p"},"h2"),", but ",(0,a.kt)("inlineCode",{parentName:"p"},"custom-element >>>> h2")," will return nothing since the inner ",(0,a.kt)("inlineCode",{parentName:"p"},"h2")," is in a deeper shadow root."),(0,a.kt)("h3",r({},{id:"p-elements"}),(0,a.kt)("inlineCode",{parentName:"h3"},"P"),"-elements"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"P")," elements are ",(0,a.kt)("a",r({parentName:"p"},{href:"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements"}),"pseudo-elements")," with a ",(0,a.kt)("inlineCode",{parentName:"p"},"-p")," vendor prefix. It allows you to enhance your selectors with Puppeteer-specific query engines such as XPath, text queries, and ARIA."),(0,a.kt)("h4",r({},{id:"text-selectors--p-text"}),"Text selectors (",(0,a.kt)("inlineCode",{parentName:"h4"},"-p-text"),")"),(0,a.kt)("p",null,'Text selectors will select "minimal" elements containing the given text, even within (open) shadow roots. Here, "minimum" means the deepest elements that contain a given text, but not their parents (which technically will also contain the given text).'),(0,a.kt)("h5",r({},{id:"example-1"}),"Example"),(0,a.kt)("pre",null,(0,a.kt)("code",r({parentName:"pre"},{className:"language-ts"}),"const element = await page.waitForSelector('div ::-p-text(My name is Jun)');\n// You can also use escapes.\nconst element = await page.waitForSelector(\n ':scope >>> ::-p-text(My name is Jun \\\\(pronounced like \"June\"\\\\))'\n);\n// or quotes\nconst element = await page.waitForSelector(\n 'div >>>> ::-p-text(\"My name is Jun (pronounced like \\\\\"June\\\\\")\"):hover'\n);\n")),(0,a.kt)("h4",r({},{id:"xpath-selectors--p-xpath"}),"XPath selectors (",(0,a.kt)("inlineCode",{parentName:"h4"},"-p-xpath"),")"),(0,a.kt)("p",null,"XPath selectors will use the browser's native ",(0,a.kt)("a",r({parentName:"p"},{href:"https://developer.mozilla.org/en-US/docs/Web/API/Document/evaluate"}),(0,a.kt)("inlineCode",{parentName:"a"},"Document.evaluate"))," to query for elements."),(0,a.kt)("h5",r({},{id:"example-2"}),"Example"),(0,a.kt)("pre",null,(0,a.kt)("code",r({parentName:"pre"},{className:"language-ts"}),"const element = await page.waitForSelector('::-p-xpath(h2)');\n")),(0,a.kt)("h4",r({},{id:"aria-selectors--p-aria"}),"ARIA selectors (",(0,a.kt)("inlineCode",{parentName:"h4"},"-p-aria"),")"),(0,a.kt)("p",null,"ARIA selectors can be used to find elements with a given ARIA label. These labels are computed using Chrome's internal representation."),(0,a.kt)("h5",r({},{id:"example-3"}),"Example"),(0,a.kt)("pre",null,(0,a.kt)("code",r({parentName:"pre"},{className:"language-ts"}),"const node = await page.waitForSelector('::-p-aria(Submit)');\n")),(0,a.kt)("h3",r({},{id:"custom-selectors"}),"Custom selectors"),(0,a.kt)("p",null,"Puppeteer provides users the ability to add their own query selectors to Puppeteer using ",(0,a.kt)("a",r({parentName:"p"},{href:"/next/api/puppeteer.registercustomqueryhandler"}),"Puppeteer.registerCustomQueryHandler"),". This is useful for creating custom selectors based on framework objects or other vendor-specific objects."),(0,a.kt)("h4",r({},{id:"example-4"}),"Example"),(0,a.kt)("p",null,"Suppose you register a custom selector called ",(0,a.kt)("inlineCode",{parentName:"p"},"lit"),". You can use it like so:"),(0,a.kt)("pre",null,(0,a.kt)("code",r({parentName:"pre"},{className:"language-ts"}),"const node = await page.waitForSelector('::-p-lit(LitElement)');\n")))}m.isMDXComponent=!0}}]);