# Hotfrog India Scraper (`crawlerbros/hotfrog-india-scraper`) Actor

Scrape Hotfrog India's local-business directory. Search by city + category/keyword, or fetch full details for known business URLs. Get name, address, phone, website, and description for restaurants, doctors, plumbers, salons, and any other business category across India.

- **URL**: https://apify.com/crawlerbros/hotfrog-india-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** Automation, Lead generation, E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## Hotfrog India Scraper

Scrape [Hotfrog India](https://www.hotfrog.in) — a free local-business directory covering restaurants, doctors, plumbers, salons, contractors, and thousands of other categories across every Indian city and town. Search by city + category/keyword (or search nationwide across all of India), or fetch full details for known business URLs. No login, no cookies, no API key required.

### What this actor does

- **Two modes:** `search` (city + category → list of businesses; leave `city` blank to search a category nationwide, or leave `query` blank to browse every category of business in one city) and `byUrls` (exact business detail lookup)
- **Core fields:** business name, address, phone number, category, city
- **Optional deep fetch:** enable `fetchFullDetails` to also pull each business's website URL, full description, geo coordinates, photos, opening hours, and payment methods (one extra request per listing)
- **Filters:** free-text keyword match, require-website, require-phone
- **Empty fields are omitted** — you'll never see `null` or `"N/A"` in the output

### Output per business

- `businessId` — Hotfrog's internal listing ID
- `businessName`
- `address`, `state`, `country` (mode=byUrls or fetchFullDetails)
- `phone`
- `fax` (mode=byUrls or fetchFullDetails; present on a subset of listings)
- `website` — only present when `fetchFullDetails`/`byUrls` resolved one
- `description`
- `latitude`, `longitude` — geo coordinates (mode=byUrls or fetchFullDetails)
- `images[]` — business photo URLs (mode=byUrls or fetchFullDetails)
- `logoUrl` (mode=byUrls or fetchFullDetails)
- `openingHours[]` — human-readable weekly hours, e.g. `"Monday, Tuesday: 09:00-18:00"` (mode=byUrls or fetchFullDetails)
- `paymentAccepted[]` — accepted payment methods (mode=byUrls or fetchFullDetails)
- `categories[]` — Hotfrog's own directory category/categories for this business, e.g. `["Restaurants"]` (mode=byUrls or fetchFullDetails; omitted when Hotfrog hasn't categorized the listing)
- `keywords[]` — the business's own directory keyword/tag list, e.g. `["Restaurant", "Italian restaurant"]` (mode=byUrls or fetchFullDetails)
- `offers[]` — `{name, url}` promotions/specials the business has published, e.g. a seasonal menu flyer (mode=byUrls or fetchFullDetails; present on a subset of listings)
- `faqs[]` — `{question, answer}` FAQ pairs Hotfrog has generated for the listing (mode=byUrls or fetchFullDetails; present on a subset of listings, mostly hotels/services)
- `isVerified` — `true` when Hotfrog shows a "Verified on Hotfrog" badge on the listing; omitted (not `false`) for unverified/unclaimed listings, since Hotfrog doesn't distinguish "checked and not verified" from "never reviewed" (mode=byUrls or fetchFullDetails)
- `verifiedAt`, `lastUpdatedAt` — UTC timestamps of when the listing was verified and last updated on Hotfrog, present only on verified listings (mode=byUrls or fetchFullDetails)
- `city` — omitted for nationwide searches (the actual per-listing city is still visible in `address`)
- `searchCategory` — the category/keyword that matched this business (search mode)
- `sourceUrl` — canonical Hotfrog India business page
- `recordType: "business"`, `scrapedAt`

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `search` | `search` / `byUrls` |
| `city` | string | `Mumbai` | Indian city (mode=search). Leave blank to search nationwide across all of India (requires `query`) |
| `query` | string | `restaurants` | Category or keyword (mode=search). Leave blank, with `city` set, to browse every category of business in that city. At least one of `city`/`query` must be set |
| `businessUrls` | array | – | Business detail page URLs (mode=byUrls) |
| `fetchFullDetails` | boolean | `false` | Also fetch each listing's detail page for `website` + full `description` |
| `keywordFilter` | string | – | Keep only businesses whose name/description/address contains this text |
| `requireWebsite` | boolean | `false` | Keep only businesses with a website populated |
| `requirePhone` | boolean | `false` | Keep only businesses with a phone number |
| `requireVerified` | boolean | `false` | Keep only businesses with a "Verified on Hotfrog" badge. Only effective with `fetchFullDetails`/`byUrls` |
| `maxItems` | integer | `30` | Hard cap on emitted records |
| `proxyConfiguration` | object | `{"useApifyProxy": true}` | Apify Proxy configuration. Enabled by default since Hotfrog India rate-limits shared datacenter IPs; can be turned off |

#### Example: restaurants in Mumbai

```json
{
  "mode": "search",
  "city": "Mumbai",
  "query": "restaurants",
  "maxItems": 30
}
```

#### Example: full-detail plumbers with a website and phone

```json
{
  "mode": "search",
  "city": "Bangalore",
  "query": "plumbers",
  "fetchFullDetails": true,
  "requireWebsite": true,
  "requirePhone": true,
  "maxItems": 20
}
```

#### Example: nationwide category search

```json
{
  "mode": "search",
  "city": "",
  "query": "wedding photographers",
  "maxItems": 50
}
```

#### Example: look up specific business URLs

```json
{
  "mode": "byUrls",
  "businessUrls": ["https://www.hotfrog.in/company/12345/example-business/mumbai/restaurants"]
}
```

### Use cases

- Build a lead list of restaurants, salons, or contractors in a given Indian city
- Enrich a CRM with phone numbers and websites for local businesses
- Research market density (how many plumbers/dentists/gyms exist per city)
- Verify a batch of known Hotfrog business URLs and pull their contact details
- Power a local-search or directory-comparison app with structured Hotfrog data
- Identify verified businesses for a partnership or advertising outreach list

### FAQ

**Does this require login or cookies?**
No. Hotfrog India is a public directory — every field in the output comes from publicly viewable pages.

**Why do some businesses have no `website` or `phone`?**
Not every business listing has that information filled in on Hotfrog. Fields that aren't available are simply omitted rather than shown as empty/null.

**Can I search any city in India?**
Yes — any city or town that Hotfrog India indexes. Larger cities return more results per category.

**Can I search all of India at once instead of one city?**
Yes — leave the `city` input blank and this actor searches Hotfrog's nationwide scope, returning matching businesses from any city/state across India.

**Can I browse every business in a city without picking a category first?**
Yes — leave `query` blank and set `city` to browse every category of business Hotfrog has listed for that city (records omit `searchCategory` since no single category was searched).

**Is proxy required?**
No. This actor uses the free Apify datacenter-equivalent access pattern and does not require a paid residential proxy.

### Limitations

- `mode=search` results depend on Hotfrog's own category matching; unusual keyword phrasing may return 0 results.
- When `requireWebsite`/`requireVerified`/`requirePhone`/`keywordFilter` are combined with `fetchFullDetails`, the actor stops early after 15 consecutive search-result pages with zero matches (instead of walking the full result set) — very restrictive filter combinations may therefore return fewer than the theoretical maximum even if a rare matching listing exists further down the list.
- Ratings/reviews counts are not reliably populated site-wide (most listings have 0 reviews), so this field is not included.
- `sourceUrl` opens normally in a real browser, but hotfrog.in's Cloudflare-backed edge returns 403 to bare `curl`/non-browser HTTP clients without a browser User-Agent — this is expected bot-detection behavior and does not indicate a broken link.
- No support for Hotfrog's other country domains (hotfrog.com, hotfrog.co.uk, etc.) — this actor is scoped to the India directory (`hotfrog.in`).
- `city`/`query` are converted to Hotfrog's Latin-only URL slugs. Accented Latin letters are folded to their plain-ASCII base automatically (e.g. `café` searches as `cafe`), but non-Latin scripts (Cyrillic, Chinese, Devanagari, etc.) have no ASCII equivalent and are dropped from the slug — use romanized/English terms for reliable results.

# Actor input Schema

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

What to fetch.

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

Indian city or town name, e.g. `Mumbai`, `Delhi`, `Bangalore`, `Pune`, `Chennai`. Leave blank to search nationwide across all of India instead of one city (requires `query` in that case).

## `query` (type: `string`):

Business category or free-text keyword, e.g. `restaurants`, `plumbers`, `dentists`, `wedding photographers`. Leave blank (with `city` set) to browse every category of business in that city instead of one category. At least one of `city`/`query` must be set.

## `businessUrls` (type: `array`):

Full Hotfrog India business/company detail page URLs (e.g. `https://www.hotfrog.in/company/<id>/<slug>/<city>/<category>`).

## `fetchFullDetails` (type: `boolean`):

For each search result, also visit its detail page to add `website` and a longer `description`. Slower (one extra request per listing) but richer output.

## `keywordFilter` (type: `string`):

Only keep businesses whose name, description, or address contains this text (case-insensitive).

## `requireWebsite` (type: `boolean`):

Only keep businesses that have a website URL populated. Only effective with `fetchFullDetails` enabled or mode=byUrls.

## `requirePhone` (type: `boolean`):

Only keep businesses with a listed phone number.

## `requireVerified` (type: `boolean`):

Only keep businesses showing Hotfrog's "Verified on Hotfrog" badge. Only effective with `fetchFullDetails` enabled or mode=byUrls (verification status is only shown on the detail page, not search results).

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

Hard cap on emitted records.

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

Hotfrog India rate-limits Apify's shared datacenter IP range, so Apify Proxy is enabled by default for reliability. You may turn it off, in which case requests go direct and simply retry with backoff.

## Actor input object example

```json
{
  "mode": "search",
  "city": "Mumbai",
  "query": "restaurants",
  "businessUrls": [],
  "fetchFullDetails": false,
  "requireWebsite": false,
  "requirePhone": false,
  "requireVerified": false,
  "maxItems": 30,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `businesses` (type: `string`):

Dataset containing all scraped Hotfrog India business listings.

# 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 = {
    "mode": "search",
    "city": "Mumbai",
    "query": "restaurants",
    "businessUrls": [],
    "fetchFullDetails": false,
    "requireWebsite": false,
    "requirePhone": false,
    "requireVerified": false,
    "maxItems": 30,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/hotfrog-india-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 = {
    "mode": "search",
    "city": "Mumbai",
    "query": "restaurants",
    "businessUrls": [],
    "fetchFullDetails": False,
    "requireWebsite": False,
    "requirePhone": False,
    "requireVerified": False,
    "maxItems": 30,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/hotfrog-india-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 '{
  "mode": "search",
  "city": "Mumbai",
  "query": "restaurants",
  "businessUrls": [],
  "fetchFullDetails": false,
  "requireWebsite": false,
  "requirePhone": false,
  "requireVerified": false,
  "maxItems": 30,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call crawlerbros/hotfrog-india-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,crawlerbros/hotfrog-india-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/QApmBQNPyTNy18DaX/builds/46HWV6XMyTeUDB1bq/openapi.json
