ScreenshotNeo

BlogAI agents

How to Use an AI Agent to Monitor Price Changes on Indian Shopping Websites with Screenshots

Build a scheduled AI-assisted monitor that records product prices and screenshots, handles uncertain results, and alerts you when a verified price changes.

By the ScreenshotNeo team4 October 202612 min read

Use a scheduled browser script to open the same product listing, read the displayed price, save a timestamped screenshot, and compare the observation with earlier runs. An AI agent can help interpret the rendered page and summarize changes, but the screenshot records only what appeared in that browser session. It does not prove that an offer was generally available, purchasable, or comparable to an earlier one.

For reliable comparisons, track the exact product variant and preserve its seller or offer context, currency, delivery region, and selected location where visible. Save ambiguous, blocked, unavailable, or failed runs for review instead of guessing a price.

1. Decide what counts as the same price

Before automating, define the product and the conditions under which two observations are comparable. A product family page may include several sizes, colors, storage capacities, or seller offers. A displayed price can also depend on the delivery location, coupons, payment method, or account state.

  • Product identity: Record a canonical URL or stable product identifier and the exact variant, such as model, size, color, or capacity.
  • Offer context: Record seller and visible offer details where practical. Do not silently compare a marketplace seller’s price with a different seller’s price.
  • Location and currency: Keep the delivery region or pincode and currency display consistent. Store the location context with each observation.
  • Price meaning: Decide whether you track the main displayed price, a sale price, or a total that includes delivery. Do not mix these values.
  • Evidence: Capture enough of the page to show the product identity and price together, rather than saving an unexplained number.

A screenshot is useful evidence of visible page content, not proof of stock, checkout eligibility, payment-method discounts, coupon conditions, delivery charges, or future availability. Check the live listing before acting on an alert.

2. Choose an implementation

For a custom AI-assisted monitor, a practical design is a scheduled Playwright script that loads a product page, extracts a price candidate, captures a screenshot, and stores a structured observation. The AI component can help interpret page content or summarize a change, but keep extraction status and uncertainty explicit. Playwright documents screenshots saved to files, full-page captures, image buffers, and screenshots of individual elements in its official screenshots documentation.

Approach Useful when Trade-offs
Playwright and a scheduled script You need control over navigation, extraction, screenshots, storage, and alert logic. You maintain browser setup, selectors, scheduling, storage, and handling for page changes and failed runs.
Managed visual website monitoring You want a service to watch page changes and send alerts. Confirm it supports the retailer, selected page area, location context, check frequency, and screenshot retention you need. Those details vary by service.
Existing price tracker app or extension A supported product and store already have the price history and alert features you want. Check exact store and product support, and whether it provides a retrievable screenshot for each check. Store listings are vendor claims, not independent tests.

Google Play and Chrome Web Store listings describe price-history and alert tools for supported Amazon and Flipkart products; one extension listing describes universal tracking as beta. Verify current support for your specific listing and whether screenshots are available. See the Google Play listing search and the Chrome Web Store listing search.

3. Build a scheduled Playwright monitor

The following Node.js example is a runnable starting point. It takes a product URL, a CSS selector for the displayed price, and an output directory. It stores the screenshot and a JSON record for every run. If the price selector is missing or its text cannot be parsed, the run is recorded as uncertain instead of inventing a value.

Install dependencies

mkdir price-monitor
cd price-monitor
npm init -y
npm install playwright
npx playwright install chromium

Save as monitor.mjs

import { chromium } from 'playwright';
import { mkdir, writeFile } from 'node:fs/promises';
import path from 'node:path';

const product = {
  name: process.env.PRODUCT_NAME ?? 'Example product, variant to be specified',
  url: process.env.PRODUCT_URL,
  priceSelector: process.env.PRICE_SELECTOR,
  currency: process.env.CURRENCY ?? 'INR',
  deliveryRegion: process.env.DELIVERY_REGION ?? 'unspecified',
};
const outputDir = process.env.OUTPUT_DIR ?? 'observations';

if (!product.url || !product.priceSelector) {
  throw new Error('Set PRODUCT_URL and PRICE_SELECTOR before running.');
}

const timestamp = new Date();
const iso = timestamp.toISOString();
const fileStamp = iso.replaceAll(':', '-');
await mkdir(outputDir, { recursive: true });
const screenshotPath = path.join(outputDir, `${fileStamp}.png`);
const recordPath = path.join(outputDir, `${fileStamp}.json`);

const browser = await chromium.launch({ headless: true });
let record = {
  timestamp: iso,
  product: product.name,
  url: product.url,
  currency: product.currency,
  deliveryRegion: product.deliveryRegion,
  screenshot: screenshotPath,
  status: 'error',
  displayedPriceText: null,
  priceCandidate: null,
  error: null,
};

try {
  const page = await browser.newPage({ locale: 'en-IN', timezoneId: 'Asia/Kolkata' });
  const response = await page.goto(product.url, { waitUntil: 'domcontentloaded', timeout: 60000 });
  record.httpStatus = response?.status() ?? null;

  // Wait for the chosen price area. A timeout becomes an uncertain observation.
  const price = page.locator(product.priceSelector).first();
  await price.waitFor({ state: 'visible', timeout: 20000 });
  record.displayedPriceText = (await price.innerText()).trim();

  // This deliberately extracts a candidate only. Validate the selector and parsing
  // against the retailer's rendered format before using a value for alerts.
  const normalized = record.displayedPriceText.replaceAll(',', '');
  const match = normalized.match(/(?:₹|Rs\.?\s*)\s*([0-9]+(?:\.[0-9]{1,2})?)/i);
  if (match) {
    record.priceCandidate = Number(match[1]);
    record.status = 'observed';
  } else {
    record.status = 'uncertain';
    record.error = 'Price text did not match the configured parser.';
  }

  // Element capture keeps the selected price and nearby product context.
  // If the selector is too narrow, use a wider stable container or a full-page shot.
  await price.screenshot({ path: screenshotPath });
} catch (error) {
  record.status = 'uncertain';
  record.error = String(error);
  // Keep a page-level image where possible so a reviewer can see an interstitial,
  // unavailable page, or changed layout. If navigation itself failed, this may fail too.
  try {
    const pages = browser.contexts().flatMap((context) => context.pages());
    if (pages[0]) await pages[0].screenshot({ path: screenshotPath, fullPage: true });
  } catch {
    record.screenshot = null;
  }
} finally {
  await browser.close();
  await writeFile(recordPath, JSON.stringify(record, null, 2));
}

console.log(JSON.stringify(record, null, 2));

Run it with values for your listing. Replace the selector with one that identifies the visible price area on the page you intend to monitor.

PRODUCT_NAME='Example phone, 128 GB, black' \
PRODUCT_URL='https://example.com/product' \
PRICE_SELECTOR='[data-testid="price"]' \
CURRENCY='INR' \
DELIVERY_REGION='your configured delivery region' \
node monitor.mjs

The example selector is illustrative; it is not a claim about any Indian retailer’s current page markup. A page redesign can invalidate it. The captured element itself may be too narrow to establish context, so choose a containing product-and-price region or use a full-page screenshot for review.

Schedule the run

Run the script from a scheduler such as cron, a CI scheduler, or a job runner you already operate. Pick an interval based on the decision you need to make and the retailer’s behavior. There is no universal best polling frequency. Avoid rapid repeated requests; review the retailer’s current terms and policies before automating access.

Keep browser locale, timezone, viewport, and delivery location stable where feasible. The sample sets locale and timezone, but it does not set a retailer delivery pincode; configure that through the retailer’s supported site flow and record what was selected. Do not assume a location cookie remains valid forever.

4. Capture useful screenshots

Choose a capture that preserves enough context to review a price later. Playwright supports the following capture styles:

// Viewport screenshot saved to a file
await page.screenshot({ path: 'page.png' });

// Entire scrollable page
await page.screenshot({ path: 'full-page.png', fullPage: true });

// Screenshot of a price or product container
await page.locator('.product-summary').screenshot({ path: 'product-and-price.png' });

// Image bytes for storage or further processing
const imageBytes = await page.screenshot();

Use an element screenshot when a stable container includes the product identity, selected variant, seller or offer details, and price. Use a full-page screenshot when important context appears elsewhere on the page. A screenshot of only the numeric price is hard to interpret later.

5. Store observations and compare safely

Keep every run, including failed or uncertain ones. A simple record can include:

  • Timestamp, product URL or stable identifier, and human-readable product and variant label.
  • Displayed price text, parsed candidate value, currency, and the parser or extraction status.
  • Visible seller and offer context, delivery region or pincode context, and relevant browser locale.
  • Screenshot file path and any navigation, selector, timeout, or parsing error.
  • Whether the page appeared unavailable, blocked, blank, or otherwise unexpected.

Compare only validated observations that match the same product variant and offer context. Mark a record for review when the selector returns multiple values, the text is ambiguous, the product is unavailable, the page shows a sign-in or interstitial screen, or the listing has changed. Do not turn missing data into zero or carry forward an old value as if it were current.

For alerts, set a target price or a change threshold that matches your use case. Include the observed value, timestamp, product link, and screenshot reference in each notification. Ask the recipient to verify the live listing before buying.

6. Add an AI agent without making it the source of truth

An AI agent can help classify page states, summarize visible changes, or turn a set of observations into a human-readable alert. Keep the browser capture and structured record as the evidence. Give the agent the screenshot and extracted text together, and ask it to return a constrained result such as:

{
  "page_state": "product | unavailable | blocked | unknown",
  "product_match": "match | mismatch | uncertain",
  "displayed_price_text": "verbatim visible text or null",
  "currency": "INR | other | unknown",
  "needs_review": true,
  "reason": "brief explanation"
}

Validate the agent’s output against the page and your product identity rules. Do not let a model infer a missing price from a prior run, guess the selected variant, or suppress a failed capture. Keep the original screenshot, raw displayed text, and agent result together so a reviewer can trace an alert.

7. Troubleshooting

Symptom Likely cause What to do
Price selector times out The page is slower than expected, the selector changed, or the product page did not load. Inspect the saved page screenshot or page state, confirm the selector against the current page, and distinguish a timeout from an unavailable product.
Price text is present but no number is parsed The displayed format differs from the example parser, or the selected text contains multiple values. Save the exact text, adjust parsing for that format, and test it against known examples. Leave the observation uncertain until validated.
The recorded product or variant is wrong The page defaulted to another variant, or the URL identifies a product family rather than a specific selection. Use a stable listing and explicitly verify the selected variant in the rendered page before comparing prices.
Screenshot shows a blank or partial page Capture occurred before the relevant content rendered, or navigation failed. Wait for a visible price container rather than relying only on a fixed delay; record failures and inspect the page state. Do not treat a blank capture as a price observation.
Price differs between runs for the same URL Seller, offer, location, currency, selected variant, or account context may have changed. Compare the surrounding context in both screenshots and records; keep the observations separate if conditions differ.
Page presents a bot check, CAPTCHA, or sign-in interstitial The retailer is challenging or gating the automated session. Do not label the interstitial as a product page or infer a price. Review the retailer’s current policies and use an allowed access method.
Browser launch fails on a server Playwright’s browser binary or required system dependencies may be missing. Install the browser for the deployed environment using Playwright’s installation instructions and inspect the runtime’s dependency requirements.
Duplicate or noisy alerts The monitor alerts on every run or compares uncertain records. Alert only on validated observations; add a configured threshold or target, and retain status so repeated failures do not look like price changes.

8. Performance, reliability, and cost

Browser runs consume time and compute, and their reliability depends on retailer page behavior, network conditions, selector stability, and the environment where the job runs. Capture only the page or element needed for review, but retain enough context to make the evidence useful. Reuse a browser process for a batch of listings when appropriate, while creating a clean page context for each product if cookies or location settings could leak between runs.

Keep screenshots and records together, use timestamped filenames, and define a retention period that fits your storage and review needs. Monitor job outcomes separately from price changes: success, uncertain page, blocked, timeout, and extraction failure should remain distinguishable. A scheduler retry can help with transient network errors, but repeated retries should not become aggressive polling.

Costs depend on where the browser job runs, how often it checks, how many products it tracks, and how long images and records are retained. Estimate runs per month as products multiplied by checks per product, then include retries and storage. The dossier provides no verified benchmark for runtime or compute cost, so measure your own workload rather than assuming a fixed price.

9. Retailer access and alternatives

Check each retailer’s current terms and policies before automating access. Flipkart’s published Terms of Use say that browsing or using the platform indicates agreement to its terms. This does not settle every question about a particular automation method, and the research here does not establish a definitive current Amazon India automation rule.

If an existing price-history app supports your exact product and provides the alerts you need, it may be simpler than maintaining a custom browser job. If you need visual monitoring, confirm the service’s retailer coverage, selected location, check interval, screenshot retention or export, notification channels, privacy terms, and failure reporting before relying on it.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server for developers. One GET request captures a URL as PNG, JPEG, WebP, or PDF. Its clean-shot flow accepts cookie or consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Only clean shots are billed: bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and billing status.

For an AI price monitor, the screenshot can serve as visual evidence to pair with your own extraction and comparison logic. It does not validate the offer or replace checks for product variant, seller, location, or current purchase conditions. See the ScreenshotNeo API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com/product -o shot.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://example.com/product"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://example.com/product'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await import('node:fs/promises').then(({ writeFile }) =>
  writeFile('shot.webp', Buffer.from(await res.arrayBuffer()))
);

ScreenshotNeo also has an MCP server with take_screenshot, get_page_info, and capture_pdf tools for AI agents and MCP clients such as Claude and Cursor. It offers 1,000 screenshots per month free with no card; paid plans start at $5 for 3,000 screenshots, and every feature is on every plan. Try the free ScreenshotNeo plan.

FAQ

Can a screenshot prove that a deal was real?

No. It shows what appeared in one browser session. Verify the live listing and offer conditions before relying on a price.

Should the agent alert on every price difference?

Only when both observations match the product variant and relevant offer context and the extraction is validated. Otherwise, flag the run for review.

How often should the monitor check a listing?

Choose an interval that fits your use case and retailer behavior. There is no universal frequency; avoid rapid repeated requests and check the retailer’s current policies.

Do I need to build a custom agent?

No. An existing tracker may cover your product and alert needs. Build a custom workflow when you need control over extraction, screenshots, records, or integrations.