# Cashify Price & Warranty Scraper (`cashi_victory/cashify-price-warranty-scraper`) Actor

"Extracts the Cashify estimated resale value of any mobile phone based on the selected city, including an optional warranty status."

- **URL**: https://apify.com/cashi\_victory/cashify-price-warranty-scraper.md
- **Developed by:** [cashify](https://apify.com/cashi_victory) (community)
- **Categories:** E-commerce, Developer tools, Lead generation
- **Stats:** 5 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Cashify Scraper (v2 — fast + per-city + per-brand)

Extracts the **estimated price** of a phone variant (based on the city) and an optional
**warranty status** from Cashify and writes them into a CSV.

Output: `data/prices_<city>_<brand>_<date>.csv` — only 3 columns:
(each **city + brand + day** gets its OWN file, so nothing is overwritten or mixed; e.g. `prices_default_apple_2026-06-19.csv`)

| device | estimate_price | warranty |
|--------|---------------|----------|
| samsung galaxy s20 ultra 5g (12 gb 128 gb) | 14070 | out_of_warranty |
| oppo a15 (2 gb 32 gb) | 2990 | out_of_warranty |

> The storage variant now appears separately in **brackets**: `model (8 gb 256 gb)`.
> `warranty` is filled only when you pass `--warranty` (a browser is required). Otherwise it is `unknown`.
> Models that return the price directly now also have their warranty checked
> (`unknown` only when the condition flow does not open at all).

---

### Setup
````

pip install playwright            # only for --warranty
python -m playwright install chromium

````

### Running
```bash
## 1) one time: find all phone URLs -> data/urls.json
python cashify_scraper.py discover

## 2) get the price for your city + your brand/model
python cashify_scraper.py scrape --city delhi --brand samsung
python cashify_scraper.py scrape --pincode 282001 --match "redmi note 13"
python cashify_scraper.py scrape --city agra              # all phones in agra
````

#### Options

| flag | meaning |
|------|--------|
| `--city <name>` | price for that city (delhi, agra, mumbai, lucknow ...) |
| `--pincode <pin>` | use a pincode instead of a city |
| `--brand <brand>` | only one brand (apple, samsung, xiaomi ...) |
| `--match "<text>"` | name must contain this text (e.g. `"galaxy a14"`) |
| `--limit N` | only N phones (for testing) |
| `--workers N` | how many phones at once (default 5; more = slightly risky) |
| `--warranty` | also extract warranty (browser, slow) |
| `--headful` | show the browser window (debug) |

#### Debug helpers

```bash
python cashify_scraper.py cities agra              # see city -> region info
python cashify_scraper.py check <variant-url> --city delhi   # test the price for one URL
```

#### Crash-safe + resume

- Every price is **saved to disk immediately** (`data/prices_<city>_<brand>_<date>.csv`), and
  progress is saved along the way (`data/done_<city>_<brand>_<date>.json`). If the script is closed
  or crashes by accident, **whatever was extracted is preserved**.
- Running the same command again **skips already-fetched phones** and continues
  from where it left off — nothing is fetched twice.
- Interactive mode looks at the old data and asks: **Continue (c)** or
  **start over (s)**. If you want a fresh run from the CLI, pass `--restart`.

***

### How it is FAST + SAFE + per-CITY (your 3 requirements)

**1. Fast, but no IP ban**

- The price now comes **directly over HTTP, not from a browser** (the Cashify page
  renders its HTML server-side and the price is in it) → ~1 sec per phone.
- Many phones **at once (in parallel)** → hours of work done in minutes.
- A plain page GET looks like a normal visitor (not a heavy bot browser) →
  lower ban risk. Even so: random jitter delay, user-agent rotation, and
  **all threads cool down as soon as a 429/403 appears** (keep `--workers` low for extra safety).

**2. City-specific value**

- Cashify gives a **different price for each city** (Delhi ₹14070 vs Agra ₹13320).
- Pass `--city`/`--pincode` → the city id is fetched from Cashify's own region API and
  a cookie is set, which yields that city's price. (Region info is cached in
  `data/regions.json`.)
- Only what you ask for is scraped — **not the whole site**.

**3. Specific brand / model**

- Use `--brand` and `--match` to get only the data you care about: e.g.
  `--brand apple` or `--match "iphone 13"` (both together as well).

**Robust even if Cashify changes its code**

- The price is extracted in **5 different ways** (if one breaks, another works).
- If the city API breaks → default-city price + a clear warning (no crash).
- The warranty buttons/questions are found by **text** (not by CSS class).

***

### v3 — Cache DB + API (Apify / RapidAPI) + Proxy fallback

#### 1. Interactive mode is now simple

`python cashify_scraper.py` → now only asks for the **brand** (city defaults to
Gurgaon, price is fast). One y/n for warranty. No other questions.

#### 2. Caching database (`data/cache.db`, SQLite)

Whatever is extracted the first time is **saved in the DB**. The next user / next
time the same thing is requested, it is returned instantly **without scraping**.

| Data | Rule |
|------|------|
| **Price** | Valid for 7 days. Old data is automatically **deleted** + re-scraped. |
| **Warranty** | Valid for 30 days. `out_of_warranty` → **PERMANENT** (never opens a browser again). `in_warranty` → rechecked after 30 days. |

> The scraper, API, and Apify all use this same DB.
> Maintenance: `python cache_db.py` (cleans old data + stats).

#### 3. HTTP API (for RapidAPI) — `api_server.py`

```bash
pip install flask waitress
python gen_key.py new "customer name"          # create your API key
set RAPIDAPI_PROXY_SECRET=<from-RapidAPI>       # block RapidAPI bypass
python api_server.py                            # dev:  http://localhost:8000
waitress-serve --port=8000 api_server:app       # production
```

| endpoint | purpose |
|----------|------|
| `GET /health` | public, is the server alive? |
| `GET /price?model=iphone-13&warranty=true` | price (+ optional warranty); brand/city/variant too |
| `GET /brands` | available brands |

Auth: header **`X-API-Key: <key>`** or through RapidAPI. Rate limit
`API_RATE_PER_MIN` (default 60/min). RapidAPI handles billing + keys itself.

#### 4. Apify Actor — `.actor/`, `Dockerfile`, `apify_main.py`

```bash
npm i -g apify-cli && apify login && apify push
```

Input: brand/model/variant/city/warranty/limit. The result goes into an Apify **dataset**.
Local test: `python apify_main.py` (or `INPUT.json`).

#### 5. Free proxies (only on block) — `proxies.py`

The normal flow is direct + fast. Only on `429/403` does it retry via a GitHub free-proxy.
Test: `python proxies.py`.

#### 6. Security

- The API key file stores only the **SHA-256 hash** (not plaintext).
- Per-key **rate limit**, **input validation**, request-size cap, debug OFF,
  no stack-trace leaks, secrets via **env var**.

***

### If it ever breaks (Cashify changed the site)

1. `python cashify_scraper.py check <some-variant-url>` — see which price
   strategy is matching.
2. Update the **CONFIG** section at the top of `cashify_scraper.py`:
   - `PRICE_STRATEGIES` → price pattern.
   - for the city: `OAUTH_URL`, `REGIONS_URL`, or the cookie name.
   - `EXACT_VALUE_BUTTON_TEXTS` / `WARRANTY_QUESTION_HINTS` → warranty.

# Actor input Schema

## `brand` (type: `string`):

Phone brand (e.g. apple, samsung, xiaomi). Use with model or on its own.

## `model` (type: `string`):

Model name (e.g. iphone 13, redmi note 13). The device name must contain this text.

## `variant` (type: `string`):

e.g. 128 gb. Leave empty for all variants.

## `city` (type: `string`):

Empty = default (Gurgaon) price. e.g. delhi, mumbai, 282001.

## `warranty` (type: `boolean`):

ON = also fetch warranty (browser, slow; result is cached). Default OFF (fast).

## `limit` (type: `integer`):

Do not return more variants than this.

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

IMPORTANT: without a proxy, Cashify may block Apify's run-IP (empty results). Default = Apify datacenter proxy (available on the free plan, rotates IP per request). On a paid plan, residential + country India works better.

## Actor input object example

```json
{
  "brand": "apple",
  "model": "iphone 13",
  "warranty": false,
  "limit": 50,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# 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 = {
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("cashi_victory/cashify-price-warranty-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 = { "proxyConfiguration": { "useApifyProxy": True } }

# Run the Actor and wait for it to finish
run = client.actor("cashi_victory/cashify-price-warranty-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call cashi_victory/cashify-price-warranty-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=cashi_victory/cashify-price-warranty-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Cashify Price & Warranty Scraper",
        "description": "\"Extracts the Cashify estimated resale value of any mobile phone based on the selected city, including an optional warranty status.\"",
        "version": "1.0",
        "x-build-id": "F0Mmrw20fiNE5g1Ya"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/cashi_victory~cashify-price-warranty-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-cashi_victory-cashify-price-warranty-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/cashi_victory~cashify-price-warranty-scraper/runs": {
            "post": {
                "operationId": "runs-sync-cashi_victory-cashify-price-warranty-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/cashi_victory~cashify-price-warranty-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-cashi_victory-cashify-price-warranty-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "brand": {
                        "title": "Brand",
                        "type": "string",
                        "description": "Phone brand (e.g. apple, samsung, xiaomi). Use with model or on its own."
                    },
                    "model": {
                        "title": "Model",
                        "type": "string",
                        "description": "Model name (e.g. iphone 13, redmi note 13). The device name must contain this text."
                    },
                    "variant": {
                        "title": "Storage variant (optional)",
                        "type": "string",
                        "description": "e.g. 128 gb. Leave empty for all variants."
                    },
                    "city": {
                        "title": "City / pincode (optional)",
                        "type": "string",
                        "description": "Empty = default (Gurgaon) price. e.g. delhi, mumbai, 282001."
                    },
                    "warranty": {
                        "title": "Fetch warranty too?",
                        "type": "boolean",
                        "description": "ON = also fetch warranty (browser, slow; result is cached). Default OFF (fast).",
                        "default": false
                    },
                    "limit": {
                        "title": "Max results",
                        "minimum": 1,
                        "maximum": 500,
                        "type": "integer",
                        "description": "Do not return more variants than this.",
                        "default": 50
                    },
                    "proxyConfiguration": {
                        "title": "Proxy",
                        "type": "object",
                        "description": "IMPORTANT: without a proxy, Cashify may block Apify's run-IP (empty results). Default = Apify datacenter proxy (available on the free plan, rotates IP per request). On a paid plan, residential + country India works better.",
                        "default": {
                            "useApifyProxy": true
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
