Shopping and listings

flipkart.com

Flipkart - Gift & Product Shopping (Field-Tested)

Notes an AI agent reads before it works on flipkart.com: what to open, what to call, what breaks. Written by browser-harness contributors after real runs, and kept on GitHub under the MIT license.

Give it to your agent

Any coding agent

Start the task with this line. The Markdown version is the same notes without the page around them.

Read https://browser-use.com/skills/flipkart.md, then <your task>

Browser Harness

Save the files into your workspace and turn domain skills on. The code below calls its helpers, such as http_get and js. What Browser Harness is.

d="${BH_AGENT_WORKSPACE:-$HOME/.config/browser-harness/agent-workspace}/domain-skills/flipkart"
mkdir -p "$d" && cd "$d"
curl -sLO https://raw.githubusercontent.com/browser-use/browser-harness/main/agent-workspace/domain-skills/flipkart/shopping.md
export BH_DOMAIN_SKILLS=1

Field-tested against flipkart.com on 2026-04-27/28 using browser-harness CDP helpers (goto_url, js, click_at_xy, type_text, capture_screenshot, scroll, press_key, page_info).


TL;DR

Build your search via URL parameters with price and category filters baked in. Dismiss the login popup immediately on every new session. For delivery checks, enter the pincode on the product page - but note that changing pincode may require login on some pages. Use __NEXT_DATA__ JSON extraction when available, fall back to DOM selectors.


Gift Search URL Template

https://www.flipkart.com/search?q={query}&marketplace=FLIPKART&p%5B%5D=facets.price_range.from%3DMin&p%5B%5D=facets.price_range.to%3D{max_price}

Example - Gifts for kids under ₹500:

goto_url("https://www.flipkart.com/search?"
         "q=gifts+for+kids+under+10+years"
         "&marketplace=FLIPKART"
         "&p%5B%5D=facets.price_range.from%3DMin"
         "&p%5B%5D=facets.price_range.to%3D500")

Example - Toys under ₹200, sorted by price:

goto_url("https://www.flipkart.com/search?"
         "q=toys+for+kids"
         "&sort=price_asc"
         "&p%5B%5D=facets.price_range.from%3DMin"
         "&p%5B%5D=facets.price_range.to%3D200")

URL Parameters Reference

ParameterTypeExampleNotes
qstringgifts+for+kidsSearch query
pageint2Pagination (1-based)
sortstringprice_ascrelevance, price_asc, price_desc, recency_desc, popularity
marketplacestringFLIPKARTRestrict to Flipkart marketplace
p[]stringfacets.price_range.from=MinMin price filter
p[]stringfacets.price_range.to=500Max price filter
p[]stringfacets.brand=SamsungBrand filter
p[]stringfacets.rating=4Minimum rating

Note: p[] parameters must be URL-encoded as p%5B%5D=facets.price_range.to%3D500.


Login Popup - MUST DISMISS FIRST

Flipkart shows a login/signup modal on every new session. It blocks all interaction until dismissed. This is the #1 cause of automation failures.

js("""(()=>{
    var btn = document.querySelector('button._2KpZ6l._2doB4z')
           || document.querySelector('[class*="close-btn"]')
           || document.querySelector('button[aria-label="Close"]');
    if (btn) { btn.click(); return 'closed'; }
    var overlay = document.querySelector('._2fS1Rz, ._3_UOR0');
    if (overlay) { overlay.click(); return 'overlay_dismissed'; }
    document.dispatchEvent(new KeyboardEvent('keydown', {key:'Escape', keyCode:27}));
    return 'escape_sent';
})()""")

If the modal persists after JS dismiss, use coordinate click on the ✕ button (typically top-right of the modal):

click_at_xy(720, 180)  # adjust based on screenshot

Delivery Check by Pincode

On search results page

Flipkart search results show estimated delivery per product. To check delivery for a specific pincode, you must visit individual product pages.

On product detail page

The delivery/pincode input is typically near the "Add to Cart" button:

# Step 1: Find and click the pincode input or "Change" link
js("""(()=>{
    var change = [...document.querySelectorAll('span, a')].find(
        e => e.textContent.includes('Change') && e.closest('[class*="pincode"], [class*="delivery"]')
    );
    if (change) { change.click(); return 'clicked change'; }
    var input = document.querySelector('input[placeholder*="pincode"], input[placeholder*="Pincode"]');
    if (input) { input.focus(); input.select(); return 'focused input'; }
    return 'not found';
})()""")
 
# Step 2: Clear and type new pincode
type_text("560077")
press_key("Enter")
 
# Step 3: Wait and read delivery estimate
wait(3)
delivery = js("""(()=>{
    var el = document.querySelector('[class*="delivery"], [class*="shipping"]');
    return el ? el.innerText.trim() : 'not found';
})()""")

Gotcha: Changing pincode on some product pages requires login. If you see a login prompt after entering pincode, the delivery check won't work without authentication. In this case, use the default delivery estimate shown on the search results page.


Product Evaluation Workflow

For gift shopping, evaluate products on these criteria:

# After navigating to a product page:
evaluation = js("""(()=>{
    var price = document.querySelector('div._30jeq3, [class*="selling-price"]')?.innerText?.trim();
    var rating = document.querySelector('div._3LWZlK')?.innerText?.trim();
    var ratingCount = document.querySelector('span._2_R_DZ')?.innerText?.trim();
    var highlights = Array.from(document.querySelectorAll('li._21Ahn-'))
                         .map(e => e.innerText.trim()).filter(Boolean);
    var delivery = document.querySelector('[class*="delivery"]')?.innerText?.trim();
    var inStock = !document.querySelector('[class*="out-of-stock"], [class*="sold-out"]');
    var seller = document.querySelector('[id*="seller"] a, div._3enH42')?.innerText?.trim();
    
    return JSON.stringify({price, rating, ratingCount, highlights, delivery, inStock, seller});
})()""")

Gift suitability checklist:

  1. Price - within budget (parse ₹ and Indian comma format)
  2. Rating - prefer 4.0+ with 50+ ratings
  3. Delivery - check pincode delivery estimate (within required days)
  4. Availability - ensure "In Stock" / "Add to Cart" visible
  5. Reusability - read highlights/description for durability indicators

Filtering on Search Results Page

By price (via sidebar click)

If you need to adjust price after page load:

# Flipkart's price filter is in the left sidebar
# Look for price range inputs
js("""(()=>{
    var inputs = document.querySelectorAll('input[class*="price"], input[name*="price"]');
    return inputs.length + ' price inputs found';
})()""")

By rating (via sidebar click)

js("""(()=>{
    var stars = [...document.querySelectorAll('div, label')].find(
        e => e.textContent.includes('4★') && e.closest('[class*="filter"]')
    );
    if (stars) { stars.click(); return 'clicked 4-star filter'; }
    return 'not found';
})()""")

By availability / delivery speed

Flipkart doesn't always expose delivery speed as a sidebar filter on all pages. When available, look for "Delivery in X days" checkboxes.


Data Extraction from Search Results

Strategy 1: __NEXT_DATA__ (Preferred)

import json
 
nd_raw = js("document.getElementById('__NEXT_DATA__')?.textContent")
if nd_raw:
    nd = json.loads(nd_raw)
    # Walk the JSON tree to find product arrays
    def find_products(obj, depth=0):
        if depth > 8: return None
        if isinstance(obj, list) and len(obj) > 3:
            if isinstance(obj[0], dict) and any(k in obj[0] for k in ['title','name','price','productId']):
                return obj
        if isinstance(obj, dict):
            for v in obj.values():
                result = find_products(v, depth + 1)
                if result: return result
        return None
    items = find_products(nd)

Strategy 2: DOM Selectors (Fallback)

results = js("""(()=>{
    var links = Array.from(document.querySelectorAll('a[href*="/p/"]'));
    var seen = new Set();
    return links.map(a => {
        var href = a.getAttribute('href');
        if (seen.has(href)) return null;
        seen.add(href);
        var card = a.closest('[data-id]') || a.closest('div[class]');
        if (!card) return null;
        return {
            title: card.querySelector('div._4rR01T, a.IRpwTa, a.s1Q9rs')?.innerText?.trim()
                || a.getAttribute('title')
                || card.querySelector('img')?.getAttribute('alt'),
            price: card.querySelector('div._30jeq3')?.innerText?.trim(),
            rating: card.querySelector('div._3LWZlK')?.innerText?.trim(),
            url: 'https://www.flipkart.com' + href,
        };
    }).filter(Boolean);
})()""")

Key Lessons (Field-Tested)

  1. URL-first strategy - Encode search query, price range, sort order, and brand filters directly in the URL. Avoid interacting with sidebar filters when possible - they trigger React re-renders that can reset scroll position.

  2. Login popup is mandatory - Every new browser session hits the login modal. Dismiss it before ANY other interaction. If JS dismiss fails, use a coordinate click on the close button.

  3. Pincode delivery check has limitations - Changing delivery pincode on product pages may require login. The search results page shows a default delivery estimate that works without login.

  4. Image overlay traps - Product pages have image zoom overlays that can capture clicks intended for other elements. If interactions stop working, press Escape first to dismiss any overlays, then retry.

  5. Indian price format - Prices use ₹ prefix with Indian grouping: ₹1,23,456 = 123,456 INR. Parse: .replace(/[₹,]/g, '').

  6. Wait 3s after wait_for_load() - Product cards load asynchronously via React. readyState=complete fires before cards render.

  7. Use new_tab() for first Flipkart load - goto_url() on the first visit can silently fail if the current tab resists navigation.

  8. Flipkart blocks datacenter IPs - Remote/headless browsers from cloud providers (e.g., Playwright Service) get ERR_CONNECTION_TIMED_OUT. Flipkart only works from residential IPs (local Chrome). For cloud-based automation, consider alternative sites like FirstCry for kids' products.

  9. Category browse pages - Use sid parameter for category navigation: https://www.flipkart.com/toys/pr?sid=tng for toys. Combine with price facets for filtered browsing.

  10. Obfuscated class names change frequently - Flipkart uses Webpack-hashed CSS classes (_4rR01T, _30jeq3). When selectors break, use a[href*="/p/"] as the stable anchor and walk up to card containers. Prefer __NEXT_DATA__ extraction which is immune to class name changes.

shopping.md · updated May 2, 2026 · 1,173 words

Sites change. These notes describe what worked when they were last updated, not a guarantee they still do. If something broke, the fix is a pull request to browser-harness.