Handling Frames

RecipeBox's recipe detail page embeds a <iframe id="nutritionFrame"> that loads nutrition information from a separate mini-page. An <iframe> is a full, independent HTML document living inside the parent page. Selenium's findElement() only searches the currently focused document — so if you try to locate something inside the iframe without switching into it first, Selenium reports NoSuchElementException even though the element clearly exists in the browser.

Three Ways to Switch Into a Frame

driver.switchTo().frame(...) is overloaded to accept an index, a name/id string, or a WebElement:

// 1. By index - position among all frames on the page, zero-based
driver.switchTo().frame(0);

// 2. By name or id attribute
driver.switchTo().frame("nutritionFrame");

// 3. By WebElement - most reliable, works even without a name/id
WebElement frameElement = driver.findElement(By.id("nutritionFrame"));
driver.switchTo().frame(frameElement);
ApproachWhen to use it
By indexQuick and dirty; breaks if frames are added/reordered. Avoid in real suites.
By name/idClean and readable, as long as the page reliably sets that attribute.
By WebElementMost robust — you locate the <iframe> tag with a normal locator first (works even if it has no name/id), then switch using that reference.

Reading Content Inside the Frame

Once switched in, findElement() operates entirely within that frame's own document:

WebElement frameElement = driver.findElement(By.id("nutritionFrame"));
driver.switchTo().frame(frameElement);

// This locator resolves inside the iframe's document, not the parent page
WebElement calories = driver.findElement(By.id("caloriesValue"));
System.out.println("Calories: " + calories.getText());

Switching Back: defaultContent()

Note: While Selenium's focus is inside a frame, it can no longer see elements on the main page. Forgetting to switch back out is one of the most common causes of a sudden "element not found" failure right after frame code. driver.switchTo().defaultContent() resets focus to the top-level page.
driver.switchTo().defaultContent();

// Now back on the main recipe detail page - this works again
WebElement backToListBtn = driver.findElement(By.id("backToListBtn"));
backToListBtn.click();

Full Worked Example

// Open a recipe's detail page (assume we already clicked into one)
WebElement frameElement = driver.findElement(By.id("nutritionFrame"));
driver.switchTo().frame(frameElement);

String calories = driver.findElement(By.id("caloriesValue")).getText();
System.out.println("Nutrition info - calories: " + calories);

// Done reading the iframe - go back to the main document
driver.switchTo().defaultContent();

// Interact with the main page again
driver.findElement(By.id("backToListBtn")).click();
Tip: If a page has frames nested inside other frames, defaultContent() jumps all the way back to the top-level document in one call — it doesn't just pop out one level. To go up exactly one level instead, use driver.switchTo().parentFrame().
Next: RecipeBox's "View Full Recipe" link opens in a brand-new browser tab — see how to handle that in Multiple Windows & Tabs.