# JustDial Data Scraper & Business Leads API (`tugelbay/justdial-leads-extractor`) Actor

JustDial data scraper for India business leads. Search by category and city; export names, public phone numbers, addresses, ratings, and listing URLs. Guide: https://konabayev.com/tools/justdial-leads-extractor/?utm_source=apify_info\&utm_medium=referral\&utm_campaign=justdial-leads-extractor

- **URL**: https://apify.com/tugelbay/justdial-leads-extractor.md
- **Developed by:** [Tugelbay Konabayev](https://apify.com/tugelbay) (community)
- **Categories:** Lead generation, Marketing
- **Features:** Limited permissions
- **Stats:** 308 total users, 11 monthly users, 65.5% runs succeeded, 3 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.24 / 1,000 business lead extracteds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

JustDial data scraper for India business leads: search a category and city or provide direct business profile URLs, then export public company names, phone numbers, addresses, ratings, listing URLs, and available detail-page fields to an Apify dataset.

[![JustDial scraper for India business leads](https://api.apify.com/v2/key-value-stores/bplRdpnd85eGQkW1N/records/justdial-leads-extractor-hero.png)](https://apify.com/tugelbay/justdial-leads-extractor)

> **Extract JustDial business leads by category and city** — try the checked `Digital Marketing Services in Borivali West` + `Mumbai` example to get structured rows with business name, available phone and address, rating, and listing URL. Availability varies by category and city.
> **Built for India B2B lead workflows** — export to CSV, Excel, Google Sheets, webhooks, CRM import, Apify API, or MCP/AI workflows.
> **Use samples to validate, then run paid production lead lists** — start with 10-20 rows, check phone/address coverage for your category and city, then add localities to build a larger list at about 10 leads per locality.
> **Pay per result** — as checked on 2026-09-23, Store pricing is $2.24 to $3.20 per 1,000 extracted businesses, depending on your Apify plan tier. An Actor-start event is charged separately.

For implementation notes, examples, and India lead-generation workflows, see the <a href="https://konabayev.com/tools/justdial-leads-extractor/?utm_source=apify_readme&utm_medium=referral&utm_campaign=justdial-leads-extractor" rel="nofollow sponsored">JustDial Leads Extractor guide</a> on Konabayev.com.

JustDial Scraper & Leads Extractor collects public business listing data from JustDial.com for sales prospecting, market research, competitor mapping, vendor sourcing, and local directory analysis in India.

Use it when you need a focused, Apify-native JustDial scraper with simple inputs, structured dataset output, scheduling, and API access.

### How to run: from sample to production

Use the first 10-20 rows to validate a category/city pair. If the sample contains useful names, phones, addresses, ratings, and listing URLs, move to a production lead-list run:

1. One category and city search returns about 10 leads. For a larger list, add the city's localities in `areas` (up to 100) and set `maxItems` to the list size you need. The Actor runs one search per locality, removes duplicates, and stops at `maxItems`.
2. Keep `includeDetails: false` for faster list building; turn it on only when websites, public emails, hours, or coordinates are worth the extra runtime.
3. Use Apify dataset export, integrations, webhooks, or the API to move the result into CSV, Excel, Google Sheets, your CRM, or an internal sales workflow.

This actor is strongest when you need repeatable India business lead lists by category and city, not one or two manual lookups.

### Fast Answers

#### Can I scrape JustDial leads and phone numbers?

Yes. This JustDial scraper extracts public business listings by category and city, including phone numbers when they are visible, business names, addresses, ratings, rating counts, and listing URLs. Optional detail enrichment can add websites, public emails, working hours, coordinates, photos count, and category breadcrumbs when JustDial exposes them.

#### Is this a JustDial business directory API?

Yes. It runs as an Apify Actor, so you can call it through the Apify API, schedule recurring category/city searches, export datasets to CSV or Excel, send results to Google Sheets, and connect the output to CRM or automation workflows.

#### When should I use a paid production run?

Use the free Apify trial or free credits for a small validation sample. Use paid production runs when you need a real India business lead list for sales prospecting, agency outreach, vendor sourcing, local market research, or recurring monitoring.

### Direct Answers for Search and AI Agents

- **JustDial scraper**: searches JustDial by category and city and returns structured business rows.
- **JustDial leads extractor**: exports India business leads with names, phones, addresses, ratings, and listing URLs.
- **JustDial phone number scraper**: captures visible public phone numbers when JustDial exposes them in the listing.
- **India business leads API**: runs through Apify API, schedules, webhooks, datasets, CSV, Excel, and Google Sheets exports.
- **Paid production fit**: best for locality-by-locality lead lists in one city at about 10 leads per locality, not one or two manual lookups.

### What This Actor Does

The actor searches JustDial by **business category** and **Indian city**, then returns one dataset item per business listing.

Default mode is intentionally fast and cheap: it extracts search-result data only. Turn on `includeDetails` when you need extra fields from each business page.

For known companies, provide **Direct business profile URLs** (`startUrls`). This mode visits the requested cards directly, validates the same business ID and its company header, and always reads available details. It does not depend on JustDial's company-name search. Category and city inputs are ignored in this mode; `city` comes from the selected profile, while the search-only fields `category`, `searchCategory` and `searchCity` are empty. `allCategories` contains the selected card's categories when visible.

### Data You Can Extract

Default search-result fields:

- business name
- category
- address
- city
- pincode when visible
- phone number when visible
- rating and rating count when visible
- verified flag when visible
- JustDial listing URL

If search returns only detail-page links, the Actor must validate those pages before emitting a billable lead, even with `includeDetails: false`. URL slugs are not used as company names; unavailable detail pages produce no fabricated lead. Unknown rating counts are `null`.

Optional detail enrichment can add:

- website URL when listed
- email when publicly visible on the page
- working-hours text when visible
- coordinates when embedded in the page
- photo count or price-range hints when visible
- additional category breadcrumbs when visible

Important: JustDial pages vary by category, city, listing type, and current frontend version. Optional fields can be empty even when the run succeeds. A run that cannot deliver at least one valid business now fails explicitly instead of returning an empty dataset with a misleading `SUCCEEDED` status.

### Reliability and fallback behavior

When JustDial maps a singular/plural category alias to its canonical category, the actor can use that source-provided category while retaining your requested city and `searchCategory`. Area-specific searches retain their original scope. This does not guarantee availability for every category or company-name search.

The actor first tries the configured India proxy through direct HTTP. If the first JustDial response is a sparse Next.js shell instead of usable listings, the actor automatically performs one owner-funded Firecrawl render fallback. The fallback has a kill switch and never exposes the Firecrawl credential as Actor input. It is deliberately limited to one request because JustDial's current rendered `/page-2` route repeats first-page results; the actor will not spend credits on duplicate rendered pages. Repeated fallback requests for the same public search URL may reuse a Firecrawl response up to 24 hours old by default, reducing latency and platform compute without reducing Firecrawl credit usage. Operators can set `JUSTDIAL_FIRECRAWL_MAX_AGE_MS=0` when a fresh render is required; the cache window is hard-capped at 48 hours.

Each selected page is validated and deduplicated before its records are checkpointed to the billable default dataset, so a later-page failure does not discard leads already delivered. Every delivered item must have a non-empty business name, city, and absolute listing URL. If neither acquisition path yields a valid item, the Actor run finishes `FAILED`; it does not create placeholder rows or charge for fabricated data. A spending-limit stop is a successful, explicitly reported early exit. The Actor bounds source work by the remaining affordable result count before proxy setup and stops when the SDK reports that the charge limit was reached. The platform can reject a run before startup when its budget cannot cover a result.

If JustDial displays "Unable to Load data" alongside a "Customers Top Picks" block, those suggested businesses are excluded from the search dataset. A run with no actual search listings fails without a lead charge. This keeps a successful run from implying that suggested cards are the requested city/category results.

An invalid input, such as a profile URL that is not a JustDial `_BZDET` business page or a malformed `areas` value, ends the run with 0 leads, no lead charge, `RUN_REPORT.terminalReason` `INVALID_INPUT`, and a status message that says what to fix. Search `maxItems` is an upper limit, not a guaranteed result count or complete city inventory. With `areas`, a run that searched every listed locality ends with `RUN_REPORT.terminalReason` `AREAS_EXHAUSTED` even when it saved fewer than `maxItems`; `RUN_REPORT` also records `areasRequested`, `areasSearched`, and `areasWithResults`. When bounded acquisition cannot continue, delivered leads remain available and the run may succeed with partial results. The status message and `RUN_REPORT.terminalReason` identify the stop (for example `FALLBACK_LIMIT`, `BLOCKED_OR_EMPTY`, `DUPLICATE_OR_INVALID`, `PAGE_LIMIT` or `TIME_GUARD`); `stoppedEarly` is true. An empty later page is not proof that no more businesses exist. These limits do not trigger additional paid retries.

### Best Use Cases

1. **India B2B lead generation** — build category-by-city prospect lists such as restaurants in Mumbai, dentists in Delhi, salons in Pune, or CA firms in Bangalore.
2. **Local market research** — estimate how many competitors exist in a city/category and compare ratings, review volume, and local coverage.
3. **Vendor sourcing** — collect plumbers, electricians, event venues, clinics, logistics providers, repair shops, and other local suppliers.
4. **CRM enrichment** — export names, phones, addresses, ratings, and listing URLs into a sales or operations workflow.
5. **Recurring monitoring** — schedule the same category/city query weekly or monthly and compare exported datasets over time.

### Why Use This Instead of Alternatives?

| Need               | This actor                              | Other Apify JustDial scrapers    | Manual research     | Generic scraper APIs       |
| ------------------ | --------------------------------------- | -------------------------------- | ------------------- | -------------------------- |
| **Input model**    | Category + city or direct profile URLs  | Often URL/search specific        | Manual search terms | Build your own parsing     |
| **Pricing model**  | Pay per extracted business              | Mixed PPE or per-item pricing    | Labor time          | API calls plus custom code |
| **Apify workflow** | Scheduler, API, datasets, webhooks, MCP | Usually available                | No                  | Requires integration work  |
| **Detail mode**    | Optional, off by default                | Varies                           | Manual clicks       | Custom implementation      |
| **Best fit**       | India lead lists and market snapshots   | Similar JustDial extraction jobs | One-off checks      | Custom data products       |

This actor's advantage is a simple, safe default path: get a quick sample with `maxItems: 10`, then add localities only for the categories and cities that produce useful data.

### Production Lead List Recipes

Use a single search with `maxItems: 10` to validate a new category/city. One search returns about 10 leads, and raising `maxItems` alone does not return more. For a production list, add 10-50 localities in `areas` and export the dataset directly to CSV, Excel, Google Sheets, webhooks, or your CRM. In a check on 2026-11-10, a city-wide search and two locality searches for restaurants in Mumbai returned 10 leads each with no overlap. Coverage varies by category and locality; a locality with no listings adds nothing and is not charged.

This actor is designed for buyers who need repeatable India business data, not one manual lookup. If you only need a few companies, manual JustDial search may be enough. If you need CRM-ready rows across many localities and cities, API calls, scheduled runs, and dataset exports are where this actor pays for itself.

Paid buyer category ideas:

These are search ideas, not verified category/city combinations. Test a 10-item sample before scaling; the checked example below is `Digital Marketing Services in Borivali West` in Mumbai.

| Paid workflow           | Category examples                                                   | City examples                          | Localities to start with |
| ----------------------- | ------------------------------------------------------------------- | -------------------------------------- | --------------------: |
| Local B2B sales         | `CA Firms`, `Digital Marketing Services in Borivali West`, `Clinics` | Mumbai, Delhi, Bangalore, Pune         |                 10-25 |
| Home services outreach  | `Plumbers`, `Electricians`, `Packers And Movers`                    | Chennai, Hyderabad, Kolkata, Ahmedabad |                 10-50 |
| Hospitality and vendors | `Restaurants`, `Hotels`, `Banquet Halls`, `Caterers`                | Mumbai, Goa, Jaipur, Delhi             |                 10-50 |
| SMB partnerships        | `Salons`, `Gyms`, `Dental Clinics`, `Repair Shops`                  | Bangalore, Pune, Surat, Chandigarh     |                 10-25 |
| Agency prospecting      | `SEO Agencies`, `Web Designers`, `Advertising Agencies`, `Printers` | Mumbai, Delhi, Pune, Hyderabad         |                  5-20 |

For a repeatable sales workflow, create one scheduled run per category/city pair and send new datasets to Google Sheets or a CRM webhook.

### Input Examples

#### Checked marketing-services category in Mumbai

```json
{
  "category": "Digital Marketing Services in Borivali West",
  "city": "Mumbai",
  "maxItems": 10
}
```

#### Dentists in Delhi with detail enrichment

```json
{
  "category": "Dentists",
  "city": "Delhi",
  "maxItems": 25,
  "includeDetails": true
}
```

#### Restaurants across Mumbai localities

```json
{
  "category": "Restaurants",
  "city": "Mumbai",
  "areas": ["Andheri East", "Borivali West"],
  "maxItems": 20
}
```

Each locality is searched once as `Restaurants in Andheri East`, `Restaurants in Borivali West`. Add more localities for a longer list.

### Input Parameters

#### Known-company profile example

```json
{
  "startUrls": [
    { "url": "https://www.justdial.com/Mumbai/Kajabi-Technologies-Maxus-Cinemas-Borivali-West/022PXX22-XX22-151219193529-U8I1_BZDET" }
  ],
  "maxItems": 1
}
```

Provide up to 100 public JustDial profile URLs ending in `_BZDET`. Duplicate business IDs are processed once. `maxItems` limits valid delivered rows; an unavailable card does not consume that result limit. No row or dataset-item charge is created for an unavailable or mismatched card. Applicable Actor-start and platform charges remain separate. Optional contact and detail fields can still be empty. The run report lists requested, attempted and failed profiles; a run with some delivered rows and failed cards is marked `PARTIAL_PROFILES` there.

With no profile URLs, category/city search remains the default. If those inputs are omitted, the demo searches Digital Marketing Services in Borivali West in Mumbai.

| Parameter            | Type    | Default                        | Required | Description                                                                                                                                                     |
| -------------------- | ------- | ------------------------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `startUrls`          | Array   | none                           | No       | Up to 100 direct JustDial business profile URLs. Takes precedence over category/city; always fetches details. |
| `category`           | String  | `Digital Marketing Services in Borivali West` | No | Business category or service keyword for search mode. Ignored when profile URLs are provided. |
| `city`               | String  | `Mumbai`                       | No       | Indian city for search mode. Ignored when profile URLs are provided. |
| `areas`              | Array   | none                           | No       | Up to 100 localities of the city. Runs one search per locality (about 10 leads each), removes duplicates, and stops at `maxItems`. Ignored when profile URLs are provided. |
| `maxItems`           | Integer | `10`                           | No       | Hard limit on total businesses to extract. One search returns about 10; add `areas` for more.                                       |
| `includeDetails`     | Boolean | `false`                        | No       | Enrich category-search results with available profile fields. Direct profile mode always reads details, even when this is false. |
| `proxyConfiguration` | Object  | Apify proxy, India residential | No       | Proxy settings. Default uses Apify Residential proxy with country `IN` for better JustDial access.                                                              |

### Output Format

Each business becomes one dataset item.

| Field            | Type           | Description                                                           |
| ---------------- | -------------- | --------------------------------------------------------------------- |
| `name`           | String         | Business name from JustDial.                                          |
| `leadSource`     | String         | Source directory, currently `JustDial`.                               |
| `extractionMode` | String         | `search` for search-result mode or `details` for detail enrichment.   |
| `searchCategory` | String         | Requested category or keyword; empty in direct profile mode.          |
| `searchCity`     | String         | Requested search city; empty in direct profile mode.                  |
| `category`       | String         | Search-listing category or query fallback; empty in direct profile mode. |
| `allCategories`  | String         | Detail-page category breadcrumbs when available.                      |
| `address`        | String         | Address text when visible.                                            |
| `city`           | String         | Business city from its JustDial listing URL, refined by the matching canonical profile when details are fetched; requested city fallback only if the source URL has no usable city. Use `searchCity` for the input city. |
| `pincode`        | String         | Six-digit pincode when detected.                                      |
| `phone`          | String         | Phone number when visible in listing text.                            |
| `email`          | String         | Public email when visible in detail-page HTML. Empty if not found.    |
| `website`        | String         | External website URL when listed.                                     |
| `rating`         | Number or null | Average rating when visible.                                          |
| `ratingCount`    | Integer / null | Rating count when visible; `null` means the source did not provide it. |
| `verified`       | String         | `Yes` / `No` / `Unknown` / empty, depending on available listing evidence. `Unknown` or empty does not mean the business is unverified. |
| `workingHours`   | String         | Recognized opening-status or weekday/time snippet; empty when no supported time expression is found. Not necessarily a full weekly schedule. |
| `latitude`       | Number or null | Latitude when embedded in the page.                                   |
| `longitude`      | Number or null | Longitude when embedded in the page.                                  |
| `photoCount`     | Integer        | Photo count when visible.                                             |
| `priceRange`     | String         | Price hint when visible.                                              |
| `url`            | String         | JustDial listing URL; updated to the canonical city/name only when the business ID matches. |
| `scrapedAt`      | String         | UTC time when this row was collected, not when JustDial updated it.  |

### Example Output

The following row is illustrative, not a claim that this business was found in the checked search.

```json
{
  "name": "Example Restaurant",
  "leadSource": "JustDial",
  "extractionMode": "search",
  "searchCategory": "Restaurants",
  "searchCity": "Mumbai",
  "category": "Restaurants",
  "address": "Andheri East, Mumbai 400069",
  "city": "Mumbai",
  "pincode": "400069",
  "phone": "09876543210",
  "email": "",
  "website": "",
  "rating": 4.2,
  "ratingCount": 148,
  "verified": "Yes",
  "workingHours": "Open until 10:30 PM",
  "latitude": null,
  "longitude": null,
  "url": "https://www.justdial.com/Mumbai/example/BZDET",
  "scrapedAt": "2026-07-14T15:30:00+00:00"
}
```

`scrapedAt` is the UTC collection time for that dataset row, not a claim that
JustDial updated the underlying listing at the same moment.

### Cost Estimation

This actor uses **Pay-Per-Event (PPE)** pricing. Each dataset item is one billable extracted business.

Business-result prices remain tiered by Apify plan:

| Plan tier | Price per business | Approx. per 1,000 businesses |
| --------- | ------------------ | ---------------------------- |
| Free      | $0.00320           | $3.20                        |
| Bronze    | $0.00288           | $2.88                        |
| Silver    | $0.00256           | $2.56                        |
| Gold+     | $0.00224           | $2.24                        |

The platform also automatically charges an Actor-start event **per allocated GB of memory, with a minimum of one event**. At the default 512 MB, one start event applies. This fee also applies when no businesses are delivered. It is separate from the per-business fee.

- Until **2026-10-25 22:45:04.551 UTC** (October 26, 03:45:04.551 in Almaty), the start event costs **$0.00005**.
- From that time, the scheduled start event costs **$0.005**. Business-result prices and every plan discount above stay unchanged.

Buyer totals at up to 1 GB (one start event):

| Valid businesses | Before activation | From activation |
| ---------------- | ----------------- | --------------- |
| 0 | $0.00005 | $0.005 |
| 1 | $0.00229–$0.00325 | $0.00724–$0.00820 |
| 2 | $0.00453–$0.00645 | $0.00948–$0.01140 |
| 10 | $0.02245–$0.03205 | $0.02740–$0.03700 |
| 100 | $0.22405–$0.32005 | $0.22900–$0.32500 |
| 1,000 | $2.24005–$3.20005 | $2.24500–$3.20500 |
| 5,000 | $11.20005–$16.00005 | $11.20500–$16.00500 |

For more memory, multiply the start fee by the allocated GB (minimum one). For example, 2 GB incurs two start events. Allow enough in the run's maximum charge for both the start and the required results. At up to 1 GB, one result needs $0.00724–$0.00820 after activation, depending on plan. Budget-limited runs stop rather than continue unbillable collection. Apify platform compute and proxy costs are included in this PPE price; your account may have separate costs for other services. The live Store Pricing tab is authoritative.

> **Plan parity:** free and paid users have the same input limits, detail fields and acquisition logic. There is no Actor monthly quota. Run spending/time limits and the independent one-call Firecrawl fallback ceiling still apply; upstream restrictions can prevent results on either plan.

### Integrations

#### Python (ApifyClient)

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")

run = client.actor("tugelbay/justdial-leads-extractor").call(
    run_input={
        "category": "Restaurants",
        "city": "Mumbai",
        "maxItems": 50,
        "includeDetails": False,
    }
)

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["name"], item.get("phone"), item.get("rating"))
```

#### LangChain

Install `langchain-apify`:

```bash
pip install langchain-apify
```

**As an agent tool:**

```python
from langchain_apify import ApifyActorsTool

leads_tool = ApifyActorsTool("tugelbay/justdial-leads-extractor")

result = leads_tool.invoke({
    "run_input": {
        "category": "Digital Marketing Services in Borivali West",
        "city": "Mumbai",
        "maxItems": 10,
    }
})
```

**As a RAG document loader:**

```python
from langchain_apify import ApifyWrapper
from langchain_core.documents import Document

apify = ApifyWrapper()
loader = apify.call_actor(
    actor_id="tugelbay/justdial-leads-extractor",
    run_input={"category": "Dentists", "city": "Delhi", "maxItems": 100},
    dataset_mapping_function=lambda item: Document(
        page_content=item.get("name") or "",
        metadata={
            "phone": item.get("phone"),
            "address": item.get("address"),
            "category": item.get("category"),
            "rating": item.get("rating"),
            "listing_url": item.get("url"),
        },
    ),
)
docs = loader.load()
```

#### JavaScript (ApifyClient)

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

const client = new ApifyClient({ token: "YOUR_API_TOKEN" });

const run = await client.actor("tugelbay/justdial-leads-extractor").call({
  category: "Dentists",
  city: "Delhi",
  maxItems: 25,
  includeDetails: true,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const business of items) {
  console.log(business.name, business.phone, business.website);
}
```

#### n8n

1. Install or add the **Apify** community node: `@apify/n8n-nodes-apify`
2. Add an **Apify** node → operation **Run Actor**
3. Authenticate with your Apify API token
4. Actor: `tugelbay/justdial-leads-extractor`
5. Input JSON:
   ```json
   { "category": "Salons", "city": "{{ $json.city }}", "maxItems": 50 }
   ```
6. Pipe output to Airtable, Google Sheets, CRM, or Slack nodes

#### Make (Integromat)

1. Add **Apify** app to scenario → module **Run an Actor**
2. Connect your Apify token
3. Actor: `tugelbay/justdial-leads-extractor`
4. Map `category`, `city`, and `maxItems` from upstream data
5. Route structured output to Make's 1,500+ apps (Airtable, Google Sheets, email, webhook)

#### Zapier

1. Create a Zap, add **Apify** as an action app → **Run Actor**
2. Authenticate with your Apify API token
3. Actor: `tugelbay/justdial-leads-extractor`
4. Map trigger data (`category`, `city`, `maxItems`) to actor inputs
5. Send extracted `name`, `phone`, `address` to Zapier's 6,000+ apps (CRM, Salesforce, Google Sheets, email)

#### MCP / AI Agents (Claude, ChatGPT, OpenAI Agents SDK)

The actor is exposed through the **Apify MCP server** at `https://mcp.apify.com` (Streamable HTTP). Any MCP-compatible client (Claude Desktop, Claude Code, ChatGPT, OpenAI Agents SDK, Vercel AI SDK) can discover and run `tugelbay/justdial-leads-extractor` as a tool. Agents pay per use via agentic payments.

#### Automated Exports

Use Apify's built-in dataset exports:

- **CSV or Excel** for spreadsheet workflows
- **Google Sheets** for live lead lists
- **Webhooks** for CRM or Slack notifications
- **Direct API** for custom apps and pipelines

### Practical Workflow

1. Start with `maxItems: 10` for one category and city.
2. Check the dataset for phone/address/rating coverage.
3. Turn on `includeDetails` only if you need websites, emails, hours, coordinates, or extra fields.
4. Increase `maxItems` after the sample looks useful.
5. Schedule recurring runs for the categories that matter.

### FAQ

#### Does it extract emails?

Sometimes. Emails are extracted only when they are publicly visible in the listing or detail-page HTML. Many JustDial listings do not expose email, so phone and listing URL should be treated as the primary contact fields.

#### Does it extract reviews?

No. The current production actor returns rating and rating count when visible. It does not currently extract individual review text.

#### Does it support search URLs or multiple searches in one run?

Search mode accepts one category and one city per run. For multiple searches, create multiple runs or schedules. Direct profile mode accepts up to 100 business card URLs in `startUrls`, including cards from different cities; search-result URLs are not supported.

#### Can I look up an exact company name?

Exact company-name search is not guaranteed. A company's direct JustDial profile may be available while its name search returns a load error or no usable listings. When you know the company's profile URL, put it in `startUrls` to read that card directly. The output still comes from JustDial; search-engine snippets are not substituted for business data.

#### Why are some fields empty?

JustDial listing layouts vary and not every business exposes phone, website, email, hours, coordinates, photos, or price hints. Empty fields mean the data was not visible or could not be parsed reliably for that listing.

For current detail-page layouts, addresses and websites come from the selected profile's contact section, not neighboring recommendations. Conflicting contact sections are not guessed. Public mobile and landline numbers can be returned when a supported phone link is visible; a hidden number is not fabricated.

#### How many results should I request?

Start with 10 to verify a category/city. One search returns about 10 leads, so for production add localities in `areas` (about 10 leads each, up to 100 localities) and set `maxItems` to the size you need. Long lists take longer and may hit site or proxy limits; the run keeps what it has already saved.

#### Is this legal to use?

This actor extracts publicly available business listing data. You are responsible for using the output lawfully, respecting JustDial's terms, privacy rules, telemarketing rules, and any local regulations that apply to outreach or resale.

### Troubleshooting

#### Detail enrichment stops with an access refusal

After an explicit source or proxy refusal during search-result enrichment, the
Actor stops making source requests and saves the already acquired, valid search
cards within the existing item and spending limits. `RUN_REPORT.stoppedEarly`
and `terminalReason` identify partial delivery. Discovery links that still need
profile validation are skipped; if no valid card remains, the run fails with zero
dataset-item charges. Profile fields are merged only after the requested business
identity is confirmed, so a mismatched page cannot replace the selected card's
name, address or contacts. Optional fields may remain empty.

#### No results found

- Check city spelling.
- Put the service in `category` and the city in `city`. For example, use
  `{"category":"Real Estate Agents","city":"Thane","maxItems":1}` instead of
  appending `thane` to the category while leaving the city as `Mumbai`.
  For a locality within a city, use `Category in Area`, as in the prefilled example.
- Try a broader category, such as `Restaurants` instead of a narrow long-tail phrase.
- Test the category/city manually on JustDial.
- Lower filters by using the simple category and city inputs only.

#### The run reports `UPSTREAM_UNAVAILABLE`

JustDial returned its own load-error page instead of usable search results. The Actor has exhausted its bounded acquisition attempts. Retry later or test a broader category/city pair on JustDial. This error does not prove that the company or its direct profile is absent. When no valid leads were delivered, there are no dataset-item charges; applicable Actor-start and platform costs are separate.

For search runs, `RUN_REPORT.sourceDiagnostics` shows whether the last page returned usable cards, a load-error page, or a CAPTCHA through direct HTTP or an attempted fallback. It distinguishes an unused fallback from a response with no usable cards. Only counts, flags, HTTP status and fixed reason categories are saved there; customer queries, URLs and page content are excluded. This helps diagnose a failed or partial run without sharing its private input.

#### The run reports `CITY_SCOPE_UNRESOLVED`

For a `City, Region` input, the source must confirm the city or locality route first. If that route cannot be verified, the Actor stops before searching the unresolved combined name or spending a Firecrawl fallback call. `RUN_REPORT.sourceDiagnostics.cityResolution` records a safe reason category and the HTTP status when available, including after a resolved search. For an area-scoped page, backend diagnostics also count parsed cards before the area filter, cards rejected by it, and whether the source area context was available and matched. A load-error page cannot validate the route. No dataset result is charged when no valid results are delivered; applicable Actor-start and platform costs remain separate. Check the city/locality on JustDial before retrying.

If you already know a company's profile URL, use `startUrls` instead of searching its name. A direct card that cannot be fetched or whose identity cannot be confirmed is skipped; a run with no valid cards fails with `PROFILE_UNAVAILABLE`.

#### Run is slow

- Keep `includeDetails` off unless needed.
- Reduce `maxItems`.
- Split large category/city lists into separate runs.
- Avoid starting many large runs at the same time.

#### Phone or email is missing

- The listing may not expose it publicly.
- Try `includeDetails: true` for extra fields.
- Use the JustDial listing URL to manually verify high-value leads.

#### Proxy or access errors

- Keep the default Apify Residential proxy with country `IN`.
- Retry later if JustDial temporarily limits access.
- Reduce run size if you repeatedly hit access issues.

### Validation evidence and official source (2026-07-14)

Validation on 2026-07-14 records what can be checked, without promising complete lead coverage:

- [JustDial](https://www.justdial.com/) is the source directory, and its current [Terms of Use](https://www.justdial.com/Terms-of-Use) are authoritative for access and downstream use.
- The dataset exposes listing URLs and only returns phone/email fields when the source makes them public; absence is a valid result.
- The Actor's schema, PPE events, metadata, links, Docker surface, and bounded input defaults pass strict local QA before release.
- Pricing in this README is a dated snapshot; the public Store Pricing tab remains authoritative.

Users must follow JustDial's terms, applicable privacy and marketing law, suppression lists, and consent requirements. This evidence does not verify ownership of a phone number, guarantee contactability, rankings, revenue, or AI citations.

### Limitations

- One category and one city per search run, or up to 100 direct business profile URLs.
- No individual review-text extraction.
- Detail enrichment is slower and field coverage varies by page.
- Emails, websites, coordinates, photos, and price hints are best-effort fields.
- Phone numbers can be absent or outdated; verify before outreach.
- Large runs can take longer and can be affected by JustDial rate limiting.
- Output reflects current JustDial pages at extraction time; it is not historical data.

### Support & Feedback

If this actor saves you time, please **[leave a review](https://apify.com/tugelbay/justdial-leads-extractor)** on its Store page — it takes under a minute and is the main trust signal that helps other users find a reliable tool.

Hit a bug or missing a feature? Open a ticket on the Actor's **Issues tab** — issues are typically answered within 24-48 hours and fixes ship fast.

### Related Actors

- [Google Maps Lead Extractor](https://apify.com/tugelbay/google-maps-leads) — Extract business leads from Google Maps
- [2GIS Scraper](https://apify.com/tugelbay/2gis-scraper) — Extract business data from 2GIS
- [Website Tech Stack Detector](https://apify.com/tugelbay/website-tech-stack-detector) — Identify technologies on any website
- [RAG Web Browser](https://apify.com/tugelbay/rag-web-browser) — Search Google and extract pages as Markdown for AI workflows

See all actors: [apify.com/tugelbay](https://apify.com/tugelbay)

### Changelog

- **2.0.42 (2026-07-02)** — Reliability pass: a remaining-run-time guard now lets large jobs finish `SUCCEEDED` with partial data instead of timing out; detail-page enrichment is skipped (and reported as `stopped_early`) once time is short instead of silently degrading; 0-lead runs caused by the time guard now report a timeout instead of a generic "check spelling" hint.

### Fallback outcome diagnostics (2026-10-24)

The first allowed fallback can return HTML without any usable listing, even
when the call budget was respected. This is `FALLBACK_NO_LISTINGS`; a fallback
that returns no document is `FALLBACK_FAILED`. `FALLBACK_LIMIT` means a later
fallback attempt was skipped after the allowed calls were already used. These
failed zero-row searches have `stoppedEarly=true`; they do not emit a paid
empty-result marker. Applicable Actor-start and provider usage remain separate.

`RUN_REPORT.firecrawlLimitReached` records whether a positive call allowance
was fully used. `firecrawlSkippedByLimit` records whether the cap actually
prevented an attempt during the run. Using the last allowed call does not by
itself make the result a budget failure. The one-call ceiling is unchanged.

The structural source diagnostics additionally retain body-text length, iframe
count, Next.js-data presence/parse failure, an explicit Next.js 404 flag and a
meta-refresh flag. They never contain the page's text, title, route, redirect
URL or query values. These flags do not change source requests or acceptance.
Original customer HTML is not reconstructed, and these changes do not establish
recovery of a historical failed search. Prices, limits, routing and retries
are unchanged.

# Actor input Schema

## `startUrls` (type: `array`):

Paste up to 100 public HTTPS JustDial business URLs ending in \_BZDET. When provided, category and city are ignored and profile details are always fetched. Use this to extract known companies whose name search fails. Duplicate business IDs are skipped; unavailable or mismatched profiles produce no dataset item. Optional fields can still be empty.

## `category` (type: `string`):

Business category or service keyword. Keep the city in the separate City field: use category Real Estate Agents + city Thane, rather than category real estate agents thane + city Mumbai. For one locality, use Category in Area with its city, as in the prefilled example; for several, use the Localities field. Other category/city pairs may be unavailable, so test a small sample before scaling. Exact company-name search is not guaranteed; use Direct business profile URLs for a known company. Ignored when profile URLs are provided.

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

Indian city name for category search (e.g., Mumbai, Delhi, Bangalore). JustDial may include listings in nearby cities; each result's city follows its business URL and searchCity keeps this input. Ignored when direct profile URLs are provided.

## `areas` (type: `array`):

One search returns about 10 leads. To build a larger list, add up to 100 localities of the city, one per line (for example Andheri East, Borivali West, Powai). The Actor runs one search per locality as Category in Locality, removes duplicates, and stops at Lead list size. Put only the service in Category and only the city in City. Localities with no listings are skipped; the run stops early if three in a row return nothing. Ignored when direct profile URLs are provided.

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

Maximum business leads to extract. Each result counts as one PPE event. One category and city search returns about 10 leads, so a larger number alone does not produce a larger list: add Localities to collect about 10 leads per locality, up to this limit. Free and paid users have the same input limits and fields; there is no Actor monthly quota. Run spending and time limits still apply.

## `includeDetails` (type: `boolean`):

Enrich category-search results with available website, public email, hours, coordinates, photo count, price hints, and categories. Optional fields are not guaranteed. Direct business profile URLs always use detail mode, even when this setting is false. For category searches, test a small sample first.

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

Proxy for accessing JustDial. Indian residential proxy required (auto-configured by default).

## Actor input object example

```json
{
  "category": "Digital Marketing Services in Borivali West",
  "city": "Mumbai",
  "maxItems": 1,
  "includeDetails": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "IN"
  }
}
```

# Actor output Schema

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

CRM-ready business leads: company name, category, city, address, phone, email, website, rating, working hours, verified status.

# 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 = {
    "category": "Digital Marketing Services in Borivali West",
    "city": "Mumbai",
    "maxItems": 1,
    "includeDetails": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("tugelbay/justdial-leads-extractor").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 = {
    "category": "Digital Marketing Services in Borivali West",
    "city": "Mumbai",
    "maxItems": 1,
    "includeDetails": False,
}

# Run the Actor and wait for it to finish
run = client.actor("tugelbay/justdial-leads-extractor").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 '{
  "category": "Digital Marketing Services in Borivali West",
  "city": "Mumbai",
  "maxItems": 1,
  "includeDetails": false
}' |
apify call tugelbay/justdial-leads-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tugelbay/justdial-leads-extractor"
        }
    }
}
```

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/XMmbymCakdjEqm3NO/builds/Orx6DBgWprP5y6dv5/openapi.json
