Is it possible to interact with inputs or other elements in an iframe?
Loadster’s browser scripts reference elements using a selector. Whenever you want the bot to click on a button, type text into a form input, or choose an option from a list, you’ll need to use a selector to point to the element you’re interacting with.
But ordinary selectors only work in the scope of a single HTML document. That’s why Loadster supports special
iframe
selectors for resolving an element nested within an iframe.
iframe[id="the-iframe"] .the-element-in-the-iframe
These iframe
selectors are necessary when you’re scripting against a site that has important interactive elements in iframes, like
a Stripe payment form or a nested video player. Because a document inside an iframe has its own DOM tree, a normal selector wouldn’t
find the nested element without a little help.
To resolve a selector within an iframe, your selector will need to specify the iframe itself as a parent element, and then reference the element inside it with an ordinary sub-selector.
For example, let’s say you have a video player nested inside an iframe, and you want the bot to click the play button of this video player. You’ll need to resolve the play button by first specifying the parent iframe, and then the play button itself.
iframe[name="video-player"] #play
Example of filling out a Stripe form
One common scripting challenge related to iframes is filling out a Stripe Elements form. These look like standard forms in the browser, but with the added complication that each form field is typically buried within its own iframe.
Because each form field is in a separate iframe, the fields aren’t part of the parent page’s DOM and can’t be
referenced by their usual selectors. Worse, the Stripe iframes themselves tend to have randomly generated IDs like
id="__privateStripeFrame5347"
so you can’t count on them being the same every time your script is played.
Instead, you can reference them by the iframe title, which is consistent.
iframe[title="Secure card number input frame"] input[name="cardnumber"]
This selector first locates the iframe titled “Secure card payment input frame” and then finds the actual input field within that iframe.
Following is an example of filling out a Stripe frame with four elements using a Loadster Code Block.
browser.type('iframe[title="Secure card number input frame"] input[name="cardnumber"]', '4242424242424242', { delay: 100 });
browser.type('iframe[title="Secure expiration date input frame"] input[name="exp-date"]', '1234', { delay: 100 });
browser.type('iframe[title="Secure CVC input frame"] input[name="cvc"]', '123', { delay: 100 });
browser.type('iframe[title="Secure postal code input frame"] input[name="postal"]', '90210', { delay: 100 });
We’ve found that the { delay: 100 }
parameter is sometimes necessary for Stripe forms, particularly for the
expiration date field, because Stripe has some client-side JavaScript that handles the keystrokes individually, and if
the bot types too fast (as bots often do) it jumbles the expiration date or other fields. For this reason it helps to
add a short 100ms delay between keystrokes when filling out Stripe forms.
Keep in mind that the bot will only be able to resolve elements inside iframes if you specify the iframe as an element
first, like in the above examples. Also keep in mind that a normal browser won’t understand these iframe
selectors –
they are a special custom extension that only works in Loadster.
Caveats and pitfalls with iframe selectors
Again, Loadster’s iframe
selectors are a custom implementation because ordinary CSS does not allow selectors
to span multiple frames. As such, they have some caveats that make them different from ordinary CSS selectors.
- A frame selector must explicitly reference
frame
oriframe
. It can’t be a bare ID or class selector like#myFrame
or.my-frame
. - A frame selector must match one unique result. If it matches multiple frames on the page it will fail.
- Nested frame selectors like
iframe[id="outer"] iframe[id="inner"] button
will work in most cases, but there may be edge cases where they don’t.