Skip to main content
Version: v2

Deep Selectors

Sites have recently begun employing newer more novel technologies like closed-shadow-DOM trees and iframes to prevent automated usage. Most libraries and frameworks don't have a good answer to these challenges as they're rather difficult to work around in a developer-friendly way. For this reason, BrowserQL supports targeting these nodes in what we call "deep selectors."

Anywhere we BrowserQL supports a "selector" argument, you can substitute this new deep-selector style syntax. Let's look at each part, in turn, and then we'll go over some examples.

Deep selectors work quite similarly to the standardized query-selector syntax you've likely used in browser-side JavaScript. However, because their use-case is different in functionality, there are some syntactic changes you should be aware of. First and foremost is their general anatomy and makeup, which is shown below:

Anatomy

selector: "< [optional URL pattern] selector"

The < character

The first item is the < character followed by a space. The < character isn't a valid DOM query-selector, and we chose it to indicate to BrowserQL that it's about to process a deep-selector and not a standard DOM selector. It is a required item to have so that it's clear, both to us as humans and to BrowserQL, that we're using this new approach.

The URL Pattern

The second item is an optional URL-pattern to match iframe documents on the page. What does this mean? Say you have a site with the following snippet of HTML on it:

<iframe src="https://facebook.com/like-this-post?post-id=123495 />
<button>Click here to like this page!</button>
<iframe>

If our site is on a different domain, say "https://browserless.io/blog/cool-post", then we can't access this "like" button on the page since the sites are on different domains. With deep selectors, you can target this specific iframe by providing a glob-style URL pattern to match this iframe's source:

selector: "< *facebook.com/like-this-post* button"

This pattern will match any urls that contain "facebook.com/like-this-post". Since the the "id" parameter might be different, having support for glob-style pattern matching means we can match any URL that has the same pattern. This means that we can match this iframe even though the ID value might change in the future.

The DOM selector

Finally, we have a required parameter of the actual DOM-selector to find this element. This syntax supports most of the modern style css selectors, including bracketed selectors like [data-button-id~="cool-button"]. However, the only selectors it won't support are hierarchical selectors, like "div button" or "span > a". Your selector must be a single node without any kind of parent/child conditions.

Examples

Target an iframe of cnn.com and look for a button with an ID of "submit"

selector: "< *cnn.com* button#submit"

Target an iframe of google.com/api/verify and click an anchor element with a classname that includes "now":

selector: "< *google.com/api/verify* a[class*='now']"

Find any element on any iframe (or top-level page) with an attribute of price:

selector: "< [price]"

Find an iframe with an exact URL of "https://amazon.com/ and a span with classname of "submit" and "order":

selector: "< https://amazon.com/ span.submit.order"

Final Thoughts

Deep selectors were created after careful thought and feedback from the community. There's actually quite a bit of automation already built around these very helpful selectors!

We encourage you to try out this new style of selector syntax and see what you think. We hope it helps you automating some of your toughest use-cases!