# Ajio Products Search Scraper (`codingfrontend/ajio-products-search-scraper`) Actor

An advanced, high-speed e-commerce scraper designed for real-time price monitoring and competitor intelligence. Extracts product titles, current pricing, discounts, stock availability, specifications, images, and seller ratings from Ajio Products Search. Perfect for inventory tracking, drop-shipp...

- **URL**: https://apify.com/codingfrontend/ajio-products-search-scraper.md
- **Developed by:** [Coding Frontned](https://apify.com/codingfrontend) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 47 total users, 4 monthly users, 99.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.99 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What does Ajio Products Search Scraper do?

This Actor extracts public product listing data from [AJIO](https://www.ajio.com/) through the site's observed JSON search response. It supports keyword searches, an Ajio `/search/` URL, and exact public product URLs; it does not log in, solve CAPTCHAs, or scrape private account data.

### Why use Ajio Products Search Scraper?

- Collect normalized Ajio product IDs, names, brands, categories, prices, discounts, seller references, and product media.
- Continue through bounded API pages, filter by price and rating when the source exposes those values, deduplicate products, and sort the collected candidate set.
- Preserve the producing search/product URL and one-based source page on every normal row.
- Use Apify scheduling, the API, run history, monitoring, and dataset exports around the Actor.

Ajio may return an access challenge or a changed response shape. The Actor fails closed, records a bounded run summary, and optionally emits a minimal diagnostic row rather than fabricating products.

### What data can it extract?

| Group | Fields |
| --- | --- |
| Identity | `productId`, `name`, `productUrl`, `relativeUrl`, `brandName`, `brandTypeName` |
| Pricing | `currency`, `price`, `priceFormatted`, `mrp`, `mrpFormatted`, `offerPrice`, `discount`, `discountPercent` |
| Classification | `segment`, `category`, `subCategory`, their source IDs, `planningCategory`, `catalogName`, `colorGroup` |
| Commercial | `couponStatus`, `volumePricesFlag`, `sizeFlag`, `maxQuantity`, `sellerId`, `sellerSku` |
| Media | `mainImage`, `images`, `allImages`, `imageDetails`, and `outfitPictureURL` when the source supplies product media |
| Provenance | `sourceMode`, `searchTerm`, `sourceUrl`, `pageNumber`, `position`, `scrapedAt` |

Optional values are omitted when AJIO does not return them. Product-listing responses do not reliably expose every detail-page field such as fit, sizes, or reviews, so those fields are not invented.

### How to scrape AJIO

1. Open the Actor's **Input** tab.
2. Select `search` and enter a query, or select `searchUrl` and provide an HTTPS AJIO `/search/` URL containing `text` or `q`.
3. For individual items, select `productUrl` and provide one to twenty HTTPS AJIO `/p/<product-code>` URLs.
4. Set filters, limits, and developer options, then start the run.
5. Download the dataset or inspect `OUTPUT` in the default Key-Value Store.

### Input

See the Input tab for the complete configuration. The runtime accepts these fields:

- **Search Sources:** `mode` (default `search`), `search`, `searchUrl`, and `productUrls`. `searchQuery` is a compatibility alias for `search`.
- **Filters and Sorting:** `priceMin` and `priceMax` (INR, default `0` means no bound), `ratings` (`""`, `"1 star & above"`, `"2 star & above"`, `"3 star & above"`, or `"4 star & above"`), and `sortBy` (`relevance`, `discount-desc`, `price-asc`, `price-desc`, `newest`, or `rating`). The legacy values `prce-asc`, `prce-desc`, and `newn` remain accepted.
- **Pagination and Limits:** `maxProductsPerSearch` (default `100`, 1–500), `maxPages` (default `10`, 1–20), and aliases `maxProducts`/`maxItems`. The product URL mode has a limit of one matched row per requested URL.
- **Dataset Fields:** `includeMedia` (default `true`) and `includeDiagnostics` (default `false`). Diagnostic rows contain only `url`, `error`, `errorCode`, and `scrapedAt` and do not count toward normal item limits.
- **Developer Options:** `requestTimeoutSecs` (10–90, default `45`), `maxRequestRetries` (0–3, default `2`), `requestDelayMs` (0–5,000, default `500`), and `proxyConfiguration`. `proxy` is the legacy alias for `proxyConfiguration`; when both are supplied, `proxyConfiguration` wins.
- **Local QA / Fixtures:** `fixtureFile` for one JSON file or `fixtureFiles` for ordered per-page JSON files. Paths must be relative and remain inside the Actor directory; these are explicit local test inputs, never a silent fallback for live failures.

Custom `searchUrl` query parameters are retained in `sourceUrl`; the Actor uses the observed AJIO API query for the normalized search term. Pages are followed using AJIO's `pagination.totalPages` metadata, up to `maxPages` per source. For non-relevance sorts, the bounded candidate set is collected before selecting the global limit. Missing numeric values sort after products with values. Identical product IDs are removed globally.

#### Simple run

```json
{
  "mode": "search",
  "search": "men sports shoes",
  "maxProductsPerSearch": 25,
  "maxPages": 1
}
```

#### Filters and global sort

```json
{
  "mode": "search",
  "search": "running shoes",
  "priceMin": 500,
  "priceMax": 5000,
  "ratings": "4 star & above",
  "sortBy": "price-asc",
  "maxProductsPerSearch": 10,
  "maxPages": 2
}
```

#### Multiple product URLs

```json
{
  "mode": "productUrl",
  "productUrls": [
    "https://www.ajio.com/example-running-shoe/p/100000001_black",
    "https://www.ajio.com/example-trail-shoe/p/100000003_green"
  ],
  "includeMedia": false
}
```

#### Developer and proxy options

```json
{
  "mode": "searchUrl",
  "searchUrl": "https://www.ajio.com/search/?text=shirts&queryId=example",
  "maxPages": 2,
  "requestDelayMs": 1000,
  "maxRequestRetries": 1,
  "requestTimeoutSecs": 30,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"],
    "apifyProxyCountry": "IN"
  }
}
```

#### Fixture-backed local QA

```json
{
  "mode": "search",
  "search": "example shoes",
  "sortBy": "price-asc",
  "maxProductsPerSearch": 3,
  "maxPages": 2,
  "requestDelayMs": 0,
  "proxyConfiguration": {"useApifyProxy": false},
  "fixtureFile": "test/fixtures/api-pages.json",
  "includeDiagnostics": true
}
```

### Output

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

A normal row is source-backed and contains the required identity, price, canonical URL, position, source mode, and timestamp fields:

```json
{
  "productId": "000000000001",
  "name": "Example Running Shoe",
  "brandName": "Example Brand",
  "currency": "INR",
  "price": 1000,
  "priceFormatted": "Rs.1,000",
  "mrp": 2000,
  "discount": "50% off",
  "discountPercent": 50,
  "mainImage": "https://assets.ajio.com/example/running-shoe.jpg",
  "images": ["https://assets.ajio.com/example/running-shoe.jpg"],
  "productUrl": "https://www.ajio.com/example-running-shoe/p/000000000001_black",
  "relativeUrl": "/example-running-shoe/p/000000000001_black",
  "sourceMode": "search",
  "searchTerm": "example shoes",
  "sourceUrl": "https://www.ajio.com/search/?text=example%20shoes",
  "pageNumber": 1,
  "position": 1,
  "scrapedAt": "2026-01-01T00:00:00.000Z"
}
```

When `includeDiagnostics` is enabled and a bounded request fails, the diagnostic shape is intentionally minimal:

```json
{
  "url": "https://www.ajio.com/search/?text=example",
  "error": "Ajio access challenge: HTTP 403.",
  "errorCode": "ACCESS_BLOCKED",
  "scrapedAt": "2026-01-01T00:00:00.000Z"
}
```

`OUTPUT` is a Key-Value Store summary containing normal and diagnostic counts, page/request outcomes, filters, duplicate and incomplete-row counts, target statuses, and elapsed time. It is operational metadata and is not mixed into the dataset.

### Tips and advanced options

Keep `maxPages`, `maxProductsPerSearch`, and detail-free media settings small for quick runs. Pagination and non-relevance sorting cost more requests because the Actor must collect the bounded candidate set before sorting. Retries, delays, and proxy routing can increase compute time. A residential proxy is used only when the configured Apify account can create it; the Actor does not bypass CAPTCHAs or access controls.

### FAQ, support, and responsible use

If a run fails, inspect `OUTPUT` for `ACCESS_BLOCKED`, `INVALID_RESPONSE`, `TIMEOUT`, or `REQUEST_FAILED`, and include the run ID when opening an Issues-tab report. Local fixture mode is explicit and is never selected automatically after a live failure.

Use the Actor only for public data and at a respectful rate. Follow AJIO's terms, robots guidance, rate limits, applicable privacy law, and any restrictions on commercial use. This Actor is not affiliated with AJIO. It does not intentionally collect private user data; users remain responsible for lawful use of any public personal data that appears in source content.

### Local validation

```bash
npm install
npm test
npm run lint
npm run validate
npm run check
apify validate-schema
apify run --purge --input-file ./qa-inputs/fixture-pagination.json
```

# Actor input Schema

## `mode` (type: `string`):

Search by keyword, scrape exact product URLs, or use an Ajio /search URL.

## `search` (type: `string`):

Required in search mode; 1–120 characters.

## `searchQuery` (type: `string`):

Compatibility alias for search when the Actor is invoked programmatically.

## `searchUrl` (type: `string`):

An HTTPS https://www.ajio.com/search/ URL containing text or q; its other query parameters are preserved as provenance.

## `productUrls` (type: `array`):

One to 20 HTTPS Ajio /p/<product-code> URLs. The public API product must match each requested code.

## `priceMin` (type: `number`):

Keep products at or above this price; 0 disables the lower bound.

## `priceMax` (type: `number`):

Keep products at or below this price; 0 disables the upper bound. It must not be below priceMin.

## `ratings` (type: `string`):

Optional source rating threshold when Ajio exposes a rating in the response.

## `sortBy` (type: `string`):

Ajio source order or a globally sorted bounded candidate set. Historical misspellings remain accepted for compatibility.

## `maxProductsPerSearch` (type: `integer`):

Global normal-record limit for a search; 1–500.

## `maxProducts` (type: `integer`):

Compatibility alias for maxProductsPerSearch.

## `maxItems` (type: `integer`):

Compatibility alias for maxProductsPerSearch.

## `maxPages` (type: `integer`):

Maximum pages fetched per source; 1–20. Ajio's totalPages metadata is followed within this bound.

## `includeMedia` (type: `boolean`):

Include product image URLs and bounded image metadata from the Ajio product payload.

## `includeDiagnostics` (type: `boolean`):

On a bounded request or parser failure, add a minimal diagnostic row with url, error, errorCode, and scrapedAt. Diagnostics do not count toward product limits.

## `requestTimeoutSecs` (type: `integer`):

Timeout for each bounded Ajio API request; 10–90 seconds.

## `maxRequestRetries` (type: `integer`):

Finite retries for transient request failures; 0–3.

## `requestDelayMs` (type: `integer`):

Respectful pacing delay between API pages; 0–5,000 ms.

## `proxyConfiguration` (type: `object`):

Apify Proxy settings used by every live Ajio API request. The proxy is transparent routing, not CAPTCHA or fingerprint bypass.

## `proxy` (type: `object`):

Compatibility alias for proxyConfiguration when invoked programmatically; ignored when proxyConfiguration is supplied.

## Actor input object example

```json
{
  "mode": "search",
  "search": "men sports shoes",
  "productUrls": [],
  "priceMin": 0,
  "priceMax": 0,
  "ratings": "",
  "sortBy": "relevance",
  "maxProductsPerSearch": 100,
  "maxPages": 10,
  "includeMedia": true,
  "includeDiagnostics": false,
  "requestTimeoutSecs": 45,
  "maxRequestRetries": 2,
  "requestDelayMs": 500,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "IN"
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

## `output` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "search": "men sports shoes",
    "productUrls": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("codingfrontend/ajio-products-search-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "search": "men sports shoes",
    "productUrls": [],
}

# Run the Actor and wait for it to finish
run = client.actor("codingfrontend/ajio-products-search-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "search": "men sports shoes",
  "productUrls": []
}' |
apify call codingfrontend/ajio-products-search-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,codingfrontend/ajio-products-search-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/WHuUyoF0aWKRYcHSO/builds/RCvFZwrSJCcSXfDYY/openapi.json
