iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
If a Puppeteer screenshot shows a blank product price, wait for the price itself to render before capturing the page. Navigation completing—or the network becoming quiet—does not prove that a client-side price has loaded. First inspect the live DOM to find out whether the element is missing, empty, hidden, inside an iframe, or waiting on a particular API response. Then wait for the relevant state and take the screenshot.
Find out what “blank” means on this page
Run the check after navigating and before adding longer waits. Inspect the exact element you expect to contain the price, including its text, visibility, and bounding box. This distinguishes a wrong selector or frame from a price that exists but has not rendered or is not visible.
const selector = '[data-testid="price"]';
const inspection = await page.evaluate((selector) => {
const el = document.querySelector(selector);
if (!el) return { found: false };
const style = getComputedStyle(el);
const rect = el.getBoundingClientRect();
return {
found: true,
text: el.textContent.trim(),
display: style.display,
visibility: style.visibility,
opacity: style.opacity,
width: rect.width,
height: rect.height
};
}, selector);
console.log(inspection);
found: false: The selector did not match in the main frame. Confirm the markup and selector, and check whether the price is in an iframe.found: truewith empty text: The element exists, but its price text has not been populated, or the selector matched a wrapper rather than the text-bearing element.- Non-empty text but zero dimensions or hidden styles: The content may not be visible in the screenshot. Check the target element and its ancestors for layout or visibility rules.
- Non-empty, visible text: The price may be rendering correctly; inspect the screenshot target, capture timing, and whether the screenshot clips the relevant area.
This is a diagnostic pattern, not a reproduction for a particular store. Without that page’s URL, selector, browser version, and code, no single cause can be confirmed.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Wait for the price state, not just navigation
Use a selector-specific wait when presence is enough, or a condition that tests for meaningful text when the screenshot must show a populated price. Puppeteer documents locators and waits for selectors and arbitrary functions in its Page API and page-interaction guide.
#1 Best Overall
- ✌Small Sign Holder: This price tag holder is made of durable acrylic material and measures 3.5" x 2" (9cm x 5cm). It provides ample space to display information while maintaining a compact footprint. You can easily to move and arrange for optimal visibility.
- ✌Elevate Display: This set of 30 L-shaped acrylic card holders is perfect for displaying business name cards, price tags, food labels, and more. Whether you're organizing a retail display, labeling food items at a buffet, or identifying seating arrangements at an event, these clear card display stands offer a practical stylish solution.
- ✌Easy to Use: This food label stand is designed in an L shape, making it easy for you to insert and take out labels. The sleek and transparent design allows your content to take center stage. The transparent exterior allows people to easily view information, making these acrylic sign holders ideal for retail displays, trade shows, events, and office settings.
- ✌Durable Material: Crafted from durable acrylic providing a sturdy base for your signage or cards. Each sign holder is wrapped in plastic to prevent scratching. Note: Please tear off the protective film on the surface of the product before use.
- ✌Satisfy Various Needs: These sign display holders can be used for offices, restaurants, trade shows, reception areas, schools, weddings, business counters, and any event to display signs, flyers, papers, images, brochures, ads, and photos.
const url = 'https://example.com/product';
const selector = '[data-testid="price"]';
await page.goto(url, { waitUntil: 'domcontentloaded' });
// Wait until the element exists and contains non-whitespace text.
await page.waitForFunction((selector) => {
const el = document.querySelector(selector);
return el && el.textContent.trim().length > 0;
}, {}, selector);
const priceText = await page.$eval(selector, el => el.textContent.trim());
if (!priceText) throw new Error('Price is still blank');
await page.screenshot({ path: 'product.png' });
Replace the example URL and selector with the product page and actual price markup. This checks for non-empty text; if your page can populate the element with a placeholder such as “Loading,” make the condition test for the actual expected format or a known completed state.
Use a locator when you also need to verify the final text
A locator can wait for the element, while a function wait checks the condition that matters. Keep the final text check before capture so an empty result fails visibly instead of silently producing another misleading screenshot.
const price = page.locator('[data-testid="price"]');
await price.wait();
await page.waitForFunction(() => {
const el = document.querySelector('[data-testid="price"]');
return el && el.textContent.trim().length > 0;
});
const text = await price.map(el => el.textContent.trim()).wait();
if (!text) throw new Error('Price is still blank');
await page.screenshot({ path: 'product.png' });
Choose the right readiness signal
| Wait strategy | What it tells you | When to use it | What it does not prove |
|---|---|---|---|
| Wait for a price selector | The selected element exists. | The page inserts the price element after navigation. | That its text is populated or it is visible. |
| Wait for non-empty or expected price text | The selected element contains text matching your condition. | The screenshot must show a rendered price. | That the text is visible or represents the correct price unless your condition checks those facts. |
| Wait for a specific API response, then check the DOM | The known request has returned; the DOM check confirms the page rendered a price. | You know which request supplies the price. | That the application successfully applied the response without the DOM check. |
| Wait for network idle | Network activity has quieted according to the selected threshold. | As a supporting signal for pages that settle after requests finish. | That application rendering is complete, or that the price exists and is visible. |
| Fixed delay | Only that a set amount of time elapsed. | As a temporary diagnostic aid to see whether extra time changes the page. | Any specific price, visibility, frame, or request state. |
Puppeteer’s screenshot guide demonstrates navigation with waitUntil: 'networkidle2' before Page.screenshot(). Network idle can be useful, but it is not a universal definition of application readiness. A Chrome for Developers example explains its use of networkidle0 as no requests for 500 ms and notes that lazy-loaded content can require more waiting; it also checks a page selector. Treat that historical example as general guidance, not as current API-version authority: Chrome Headless. A Puppeteer waiting guide dated September 16, 2026, likewise cautions against treating network idle as a universal “done” signal: Puppeteer wait-for-page guidance.
Rank #2
- Adjustable Price Tags for Retail: This set includes 16 adjustable price display stands, each featuring a versatile aluminum base and acrylic panels. Ideal for a wide range of retail settings, including jewelry stores, supermarkets, and bakeries, it offers a secure and professional way to display prices.
- Durable and Easy-to-Use Design: Made from eco-friendly and lightweight ABS and aluminum materials, this price tag display stand is built to last. Each block is easy to adjust, and the entire system is simple to assemble with no glue or tools required, ensuring a hassle-free setup.
- Perfect for Multiple Price Displays: Each set includes 192 price blocks, including numbers 0-9, the dollar sign ($), and a decimal point, so you can easily display any price. The included acrylic panels also allow you to insert paper tags with your custom prices, offering flexibility for all price points.
- Ideal for Various Applications: Whether you're showcasing jewelry, watches, baked goods, or products in supermarkets, this adjustable counter stand is the perfect choice. Its sleek and professional design makes it ideal for any display case or counter.
- Convenient and Compact Packaging: The set includes 16 complete price tag displays, with each set containing a block kit, acrylic panels, and aluminum base. Compact and easy to store, the set provides everything you need to create a professional price display setup.
Wait for the price request when you know it
If a particular API response controls the price, wait for that response and then verify the rendered text. The response is a more targeted signal than general network quiet, but it does not by itself prove that the page applied the price or made it visible.
const priceResponsePromise = page.waitForResponse(response =>
response.url().includes('/api/product-price') &&
response.request().method() === 'GET'
);
await page.goto(url, { waitUntil: 'domcontentloaded' });
const priceResponse = await priceResponsePromise;
if (!priceResponse.ok()) {
throw new Error(`Price request failed: ${priceResponse.status()}`);
}
await page.waitForFunction(() => {
const el = document.querySelector('[data-testid="price"]');
return el && el.textContent.trim().length > 0;
});
await page.screenshot({ path: 'product.png' });
Adjust the URL match and method to identify the actual request; avoid matching a broad URL fragment if unrelated requests could satisfy the wait. If the request may happen before navigation is initiated, create the response wait first, as above. A failed or non-OK response should be handled explicitly rather than followed by a long arbitrary sleep.
Check whether the price is in an iframe
A page-level selector searches the main frame, not every iframe’s document. If inspection suggests the price is embedded, find the matching frame and query inside it. The frame may also appear asynchronously, so wait for it before checking the price.
Rank #3
- Multi-purpose Shelf Label Holders:It can be placed with included adhesive nanogel dots,or just sit directly on the tabletop.Perfect as book shelf labels,retail tags,sign holder,product information display and display stand.For library,school,bookstore,home,classroom,store,bakery,market,etc. be pasted or placed. Easy to change the inserts.
- Label Holders in 4 Ways to Display: Attach it to the edge of the shelf to display your label vertically for side views; Lay your label flat on the surfaces for overhead reading; Stand freely on surface for 45° angled viewing; Adhere the base with the adhesive sticker for 90° upright display.The 90-degree design ensures a flush fit against the shelf.
- High Transparency Acrylic Sign Holder: Made of high quality acrylic material,high transparency,make your label clean and tidy.
- Sutiable size for shelves: Label area is 1.25"x3.15",it is just right, not too big, so it won't interfere with taking items from the next layer.
- Please note:Peel off the white protective film covering the label holders before use.The protective film is not clear.
await page.goto(url, { waitUntil: 'domcontentloaded' });
await page.waitForFunction(() =>
[...document.querySelectorAll('iframe')].some(frame =>
frame.src.includes('pricing')
)
);
const priceFrame = page.frames().find(frame =>
frame.url().includes('pricing')
);
if (!priceFrame) throw new Error('Price iframe was not found');
const selector = '[data-testid="price"]';
await priceFrame.waitForFunction((selector) => {
const el = document.querySelector(selector);
return el && el.textContent.trim().length > 0;
}, {}, selector);
const priceText = await priceFrame.$eval(selector, el => el.textContent.trim());
console.log(priceText);
await page.screenshot({ path: 'product.png' });
Replace the frame URL test with a stable identifier from the page. If several frames are present, identify the one that actually contains the price rather than choosing the first frame. The final page screenshot captures the rendered page; use the frame query to confirm the price state before capture.
Capture only after validation
When the price text is present and visible, capture the page. Puppeteer’s official guide says, “For capturing screenshots use Page.screenshot().” For a focused capture, ElementHandle.screenshot() is also documented and attempts to scroll an element into view if it is hidden; see the Puppeteer screenshot guide.
await page.screenshot({ path: 'product.png', fullPage: true });
For an element-only image, first verify that the selected element is the actual price target, then use its handle:
Rank #4
- MATERIAL & SIZE: Made of ABS and wood, lightweight, durable and long lasting, not easy to break. Each wood stand size-approx.: 57mm/2.44” x 20mm/0.79” (L x W). Small and exquisite size for easy storage and display.
- APPLICATIONS: Ideal for retail shop window counter, such as jewelry, watches, cigarettes, makeups, clothing, wine, supermarkets, bakeries and other price displays.
- ADJUSTABLE PRICE TAG: Each cube is adjustable, easy to assembly the digits together without glue, and you can freely change price for your needs.
- REUSABLE PRICE DISPLAY HOLDER: These jewelry pricing cubes are flexible, can be used again and again, affordable and cost-effective. Featuring with pentagonal sections for multi-angle placement and extreme stability, show valence for customers with perfect visual angle, make the price more obvious and impressive.
- PACKAGE INCLUDES: Each set consists of 2 separable cubes , and 10 wood base, 10 sets have 130 cubes,10 bases totally, including "$", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", ".","00".
const priceElement = await page.$('[data-testid="price"]');
if (!priceElement) throw new Error('Price element was not found');
await priceElement.screenshot({ path: 'price.png' });
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Troubleshoot the common failure modes
- The wait times out: Re-run the DOM inspection. Confirm the selector matches current markup and that the page reached the expected state. If the price is in a frame, query the frame instead of the main page.
- The selector matches, but text remains empty: Check whether the request supplying the price failed or is still pending. Wait for that request if known, then re-check rendered text.
- Text is present in the DOM but absent from the image: Inspect computed visibility and bounding-box dimensions, then confirm the screenshot includes the relevant viewport or full page. A hidden element is not equivalent to a visible price.
- Network idle completes but the price is blank: Replace it as the sole condition with a price-specific text check. Network quiet measures activity, not application correctness.
- A fixed sleep appears to work intermittently: Keep it only as a diagnostic clue. Replace it with a selector, text condition, or known response plus DOM validation so slower loads do not recreate the problem.
- The API wait times out or reports failure: Check that the match identifies the correct endpoint and method, inspect the response status, and verify that the page actually requested it. Do not proceed to the screenshot as if the price had loaded.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. One GET request can return a PNG, JPEG, WebP, or PDF. Its clean-shot steps accept cookie and consent banners like a visitor and remove more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and each response includes X-Page-Verdict and X-Billed headers. AI agents can use its MCP tools take_screenshot, get_page_info, and capture_pdf.
For a product page, make the one-call request and save the returned image:
Free tools Windows power users keep installed
One-click scans. No signup required.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com/product -o shot.webp
See the ScreenshotNeo API documentation for request options. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Sign up for ScreenshotNeo’s free plan.
Why this fix is more reliable
A navigation event tells you about document loading, not whether a client-rendered product price has become meaningful. The reliable condition is the one the screenshot needs: the correct price element has non-empty text and is visible. If a known request or iframe is involved, check that context as well; then capture only after validation.
Best Value
- Sapele wood base offering a rich, warm grain that adds sophisticated texture to any setting, from retail counters to banquet table. Elevate tabletop with this small yet elegant sign holder
- The panel accommodates inserts up to 2.36"x1.97". Design tip: allow a 0.4" bottom margin in your content, as the base overlaps this area to guarantee a clean, professional look
- NOTE: For clear display, first peel off the protective film from the panel. For stable setup, first press the panel onto the rubber strip. Then, insert this into the slot on the wood base
- Crafted from durable acrylic and hardwood, this holder is ideal for dynamically displaying daily specials, product prices, dessert names, or guest place cards with effortless style
- Stable for Daily Use: Sapele wood base offers excellent stability on countertops and buffet lines, preventing tipping even in busy retail or dining environments
Frequently Asked Questions
Does `networkidle2` guarantee the product price has loaded?
No. It is a network-activity signal, not proof that the price text exists or is visible. Pair it with a price-specific DOM check.
Why does `waitForSelector()` succeed while the screenshot still has no price?
The selector wait establishes that an element matched; it does not necessarily establish that its text is populated, visible, or in the expected frame.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Can a fixed timeout solve a blank price screenshot?
It may help diagnose whether more time changes the page, but it does not verify the price state and can be unreliable across load conditions.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

