LeadGen.tools API
Programmatic access to lead generation, web scraping, ad intelligence, and Google Places data. Integrate our tools directly into your applications and workflows.
Introduction
The LeadGen.tools REST API lets you search for leads, crawl websites for contact information, monitor competitor ads, and query Google Places — all from simple HTTP GET requests.
Every request is authenticated with your API key and user ID. Operations consume credits from your account balance, and responses are automatically cached to save credits on repeated queries.
Quick Start
Make your first API call in seconds:
curl "https://leadgen.tools/v2/api/v1/search.php?api_key=YOUR_KEY&user_id=123&query=marketing+agency+new+york&se=google"
Authentication
Every API request requires two parameters:
| Parameter | Type | Description |
|---|---|---|
| api_key Required | string | Your Softsale license key. Found in your account dashboard under "API Key". |
| user_id Required | integer | Your aMember user ID. Found in your account profile. |
Both parameters are sent as query string parameters on every request:
GET /api/v1/search.php?api_key=YOUR_KEY&user_id=123&query=...
Keep your API key secret
Never expose your API key in client-side code, public repositories, or shared URLs. Treat it like a password.
Base URL
All API endpoints are accessed under:
https://leadgen.tools/v2/api/v1/
For example, the full URL for the Lead Search endpoint is:
https://leadgen.tools/v2/api/v1/search.php
Response Format
All responses are returned as JSON with the Content-Type: application/json; charset=utf-8 header.
Success Response
{
"status": "success",
"credits_used": 10,
"data": {
// endpoint-specific data
}
}
Error Response
{
"status": "error",
"code": "error_code",
"message": "Human-readable description of the error."
}
The credits_used field tells you how many credits were deducted for that request. A value of 0 means the response was served from cache or no billable results were returned.
Error Handling
Errors return an appropriate HTTP status code along with a JSON body containing a machine-readable code and a human-readable message.
| HTTP Status | Error Code | Description |
|---|---|---|
| 400 | missing_param |
A required parameter is missing from the request. |
| 400 | invalid_param |
A parameter value is invalid (e.g. unsupported search engine). |
| 400 | invalid_code |
Recipe code not found or invalid (search endpoint only). |
| 401 | missing_api_key |
The api_key parameter was not provided. |
| 401 | missing_user_id |
The user_id parameter was not provided. |
| 400 | invalid_user_id |
The user_id must be a positive integer. |
| 401 | invalid_api_key |
API key is invalid, expired, or not recognized. |
| 402 | insufficient_credits |
Your account has no credits remaining. Purchase more to continue. |
| 500 | db_error |
Internal database connection error. |
| 502 | search_error |
The upstream search request failed. Retry after a few seconds. |
| 502 | crawl_error |
Could not fetch the provided URL. |
| 502 | api_error |
Upstream Google API error (Places endpoints). |
| 503 | auth_error |
License verification service unavailable. Retry later. |
Tip: Credits are never deducted when an error occurs. You are only charged for successful operations that return data.
Credit System
Each API operation costs credits, which are deducted from your account balance. The exact cost depends on the endpoint and the results returned.
| Endpoint | Credits | Details |
|---|---|---|
| Lead Search | 0 – 10 | 10 credits if >7 results returned. Otherwise, 1 credit per email found in the SERP. 0 if no results. |
| Website Crawler | 0 – 15 | 1 credit per unique valid email found. Minimum 1 credit if any data (emails, phones, or social links) is returned. 0 if nothing found. |
| Ad Spy | 0 – 10 | 10 credits if >7 fresh ads returned. Otherwise, 1 credit per ad containing an email. Crawl enrichment and historical ads are free. |
| Places Search | 0 – 200 | 10 credits per place detail lookup (cache miss). 0 credits for cached places. Up to 20 places per page. |
| Place Reviews | 0 or 5 | 5 credits on cache miss (fresh Google API call). 0 credits if reviews are cached within 7 days. |
Cache hits are free. When a response is served from cache, credits_used will be 0. Caching is automatic — repeated identical queries save you credits.
Caching
Responses are automatically cached to reduce latency and save credits. If an identical request has been made recently, the cached response is returned instantly with credits_used: 0.
| Endpoint | Cache TTL | Notes |
|---|---|---|
| Lead Search | 7 days | Same query + search engine + page + results_per_page |
| Website Crawler | 14 days | Same domain URL |
| Ad Spy | Permanent | Individual ads stored permanently. Crawl data refreshed every 7 days. Each request always performs a fresh search. |
| Places Search | 30 days | Per-place cache based on place_id |
| Place Reviews | 7 days | Per-place cache based on place_id |
Rate Limits
There are currently no hard rate limits enforced per-minute. However, some endpoints involve upstream API calls (ScraperAPI, Google Places) that may take several seconds to complete. Recommendations:
- Keep concurrent requests reasonable (under 5 simultaneous).
- Use the caching system — avoid polling the same query repeatedly.
- The crawler endpoint can take up to 2 minutes for deep crawls (up to 15 pages). Set your HTTP client timeout accordingly.
- Ad Spy with crawl enrichment may take 30–60 seconds on first call (crawling up to 15 ad landing pages).
Lead Search
Search Google, Bing, Yahoo, or DuckDuckGo for leads. Returns page titles, links, descriptions, and any emails or phone numbers found in the search results. You can pass a raw dork query or a saved recipe code.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| api_key Required | string | — | Your API key. |
| user_id Required | integer | — | Your user ID. |
| query Required* | string | — | The search query or Google dork (e.g. "marketing agency" "new york"). Required unless code is provided. |
| code Optional* | string | — | A saved recipe code. Alternative to query — resolves to a pre-defined dork command. Use one or the other. |
| se Optional | string | google |
Search engine. One of: google, bing, yahoo, duckduckgo |
| page Optional | integer | 0 |
Pagination offset. Increment to fetch the next page of results. |
| results_per_page Optional | integer | 10 |
Number of results per page. |
Example Request
curl "https://leadgen.tools/v2/api/v1/search.php?\ api_key=YOUR_KEY&\ user_id=123&\ query=marketing+agency+new+york&\ se=google&\ page=0&\ results_per_page=10"
Example Response
{
"status": "success",
"credits_used": 10,
"data": {
"query": "marketing agency new york",
"search_engine": "google",
"page": 0,
"results_count": 10,
"results": [
{
"title": "Top Marketing Agency in NYC | Example Agency",
"link": "https://www.exampleagency.com/",
"description": "Award-winning digital marketing agency based in New York City...",
"emails": ["hello@exampleagency.com"],
"phones": ["(212) 555-0147"]
},
{
"title": "Creative Digital Agency NYC",
"link": "https://www.creativeagency.io/",
"description": "We help brands grow with data-driven campaigns...",
"emails": [],
"phones": []
}
]
}
}
Credit Calculation
- More than 7 results returned → 10 credits (flat)
- 7 or fewer results → 1 credit per email found in the SERP (junk emails like
example@wix.comare excluded) - No results → 0 credits
- Cache hit → 0 credits
Website Crawler
Crawl a website to extract emails, phone numbers, social media links, and page metadata. Automatically follows internal links and crawls up to 15 pages for thorough data extraction.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| api_key Required | string | — | Your API key. |
| user_id Required | integer | — | Your user ID. |
| domain Required | string | — | The URL to crawl. If no protocol is provided, https:// is prepended automatically. Example: example.com or https://example.com |
Example Request
curl "https://leadgen.tools/v2/api/v1/crawl.php?\ api_key=YOUR_KEY&\ user_id=123&\ domain=example.com"
Example Response
{
"status": "success",
"credits_used": 3,
"data": {
"domain": "https://example.com",
"pages_crawled": 8,
"metadata": {
"title": "Example Company — Home",
"description": "We provide enterprise solutions for...",
"keywords": "enterprise, solutions, consulting",
"image": "https://example.com/og-image.jpg"
},
"emails": [
"contact@example.com",
"sales@example.com",
"hr@example.com"
],
"all_emails": [
"contact@example.com",
"sales@example.com",
"hr@example.com",
"support@otherdomain.com"
],
"phones": [
"(555) 123-4567",
"(555) 987-6543"
],
"social_links": [
"https://twitter.com/example",
"https://www.linkedin.com/company/example",
"https://www.facebook.com/example"
]
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
| domain | string | The normalized URL that was crawled. |
| pages_crawled | integer | Total number of pages crawled (max 15). |
| metadata | object | Page metadata: title, description, keywords, and image (Open Graph). |
| emails | string[] | Valid emails matching the crawled domain only. |
| all_emails | string[] | All emails found, including those from other domains. |
| phones | string[] | Phone numbers extracted from all crawled pages. |
| social_links | string[] | Social media profile URLs (Facebook, Twitter/X, LinkedIn, Instagram, YouTube, TikTok, Pinterest, Snapchat, Telegram, WhatsApp, Spotify). |
Credit Calculation
- 1 credit per unique domain-matched email found
- Minimum 1 credit if any data (emails, phones, or social links) is returned
- No data found → 0 credits
- Cache hit → 0 credits
How the Crawler Works
- Fetches the main page at the provided URL.
- Extracts emails, phones, social links, and metadata from the HTML.
- Discovers internal links on the page.
- Crawls up to 14 additional internal pages (15 total max).
- Merges and deduplicates all results.
Email filtering: Junk emails are automatically excluded — website builders (wix, squarespace), placeholder domains (example.com, yourname.com), generic local parts (admin, noreply, test), and image file extensions.
Ad Spy
Search for Google and Bing ads, automatically accumulate historical results, and enrich each ad with contact data by crawling the landing page. Every search adds newly discovered ads to a permanent database, so repeated queries return both fresh ads (currently running) and historical ads (previously seen).
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| api_key Required | string | — | Your API key. |
| user_id Required | integer | — | Your user ID. |
| query Required | string | — | The ad search query (e.g. marketing agency). |
| se Optional | string | google |
Search engine. One of: google, bing |
| page Optional | integer | 0 |
Pagination offset for the live SERP search. |
| include_history Optional | boolean | true |
Include historical ads from previous searches. Set to false to only return fresh ads from this search. |
Example Request
curl "https://leadgen.tools/v2/api/v1/ads.php?\ api_key=YOUR_KEY&\ user_id=123&\ query=marketing+agency&\ se=google&\ include_history=true"
Example Response
{
"status": "success",
"credits_used": 10,
"data": {
"query": "marketing agency",
"search_engine": "google",
"page": 0,
"fresh_count": 5,
"historical_count": 3,
"results_count": 8,
"results": [
{
"position": 1,
"title": "Best Marketing Agency | Award-Winning",
"url": "https://www.exampleagency.com/",
"ad_text": "Full-service digital marketing agency. Get a free audit today...",
"search_engine": "google",
"first_seen": "2025-01-15 10:00:00",
"last_seen": "2026-02-15 14:30:00",
"is_active": true,
"contact_data": {
"emails": ["info@exampleagency.com"],
"phones": ["(555) 123-4567"],
"social_links": [
"https://facebook.com/exampleagency",
"https://linkedin.com/company/exampleagency"
],
"metadata": {
"title": "Example Agency — Digital Marketing",
"description": "Award-winning agency specializing in SEO, PPC, and social media.",
"keywords": "marketing, agency, SEO, PPC",
"image": "https://www.exampleagency.com/og-image.png"
}
}
},
{
"position": 3,
"title": "Grow Your Business | Old Ad Agency",
"url": "https://www.oldagency.com/",
"ad_text": "We help businesses scale with proven strategies...",
"search_engine": "google",
"first_seen": "2024-11-02 08:15:00",
"last_seen": "2025-12-20 11:00:00",
"is_active": false,
"contact_data": {
"emails": ["hello@oldagency.com"],
"phones": [],
"social_links": ["https://twitter.com/oldagency"],
"metadata": {
"title": "Old Agency",
"description": "",
"keywords": "",
"image": ""
}
}
}
]
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
| fresh_count | integer | Number of ads found in the current live search. |
| historical_count | integer | Number of additional ads from previous searches. |
| results_count | integer | Total number of results (fresh + historical, deduplicated). |
| results[].position | integer | Ad position on the SERP. |
| results[].first_seen | datetime | When this ad was first discovered. |
| results[].last_seen | datetime | When this ad was last seen in a live search. |
| results[].is_active | boolean | true if the ad appeared in the current search, false if it's historical only. |
| results[].contact_data | object | Contact information extracted from crawling the ad's landing page. Contains emails, phones, social_links, and metadata. |
How It Works
- Fresh search — Performs a live Google/Bing search to find currently running ads.
- Store — Each fresh ad is saved to a permanent database. New ads are inserted; existing ads have their
last_seentimestamp updated. - Load history — All previously stored ads for the same query are loaded and merged.
- Crawl enrichment — Each ad's landing page URL is crawled to extract emails, phones, social links, and page metadata. Up to 15 ads are crawled per request. Crawl results are cached for 7 days.
- Return — Results are returned sorted by
last_seen(most recent first), withis_activeindicating whether each ad appeared in the current live search.
Historical accumulation: Every time you search the same query, newly discovered ads are added to the pool. Over time, you build a comprehensive database of all ads that have ever run for that keyword. Use first_seen and last_seen to track ad lifespan.
Credit Calculation
- Credits are based on fresh results only (historical and crawl enrichment are free).
- More than 7 fresh ads → 10 credits
- 7 or fewer fresh ads → 1 credit per ad containing an email
- No fresh ads → 0 credits (but historical results are still returned)
Places Search
Search Google Places for businesses by keyword. Returns detailed listings including name, address, phone, website, rating, business hours, and more. Results are cached for 30 days to save credits.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| api_key Required | string | — | Your API key. |
| user_id Required | integer | — | Your user ID. |
| keyword Required* | string | — | Search query (e.g. restaurants new york). Required unless pagetoken is provided. |
| pagetoken Optional | string | — | Pagination token from a previous response's next_page_token field. Used to fetch the next page of results. |
Example Request
curl "https://leadgen.tools/v2/api/v1/places/search.php?\ api_key=YOUR_KEY&\ user_id=123&\ keyword=restaurants+new+york"
Example Response
{
"status": "success",
"credits_used": 40,
"data": {
"keyword": "restaurants new york",
"results_count": 4,
"next_page_token": "AeJbb3eFR...",
"results": [
{
"url": "https://maps.google.com/?cid=...",
"name": "Joe's Pizza",
"address": "7 Carmine St, New York, NY 10014",
"phone": "(212) 366-1182",
"website": "https://www.joespizzanyc.com/",
"rating": 4.4,
"rating_total": 8732,
"types": ["restaurant", "meal_delivery", "food"],
"weekday_text": [
"Monday: 10:00 AM \u2013 2:00 AM",
"Tuesday: 10:00 AM \u2013 2:00 AM"
],
"icon": "https://maps.gstatic.com/...",
"open_now": true,
"place_id": "ChIJr3_gqu5ZwokR...",
"business_status": "OPERATIONAL",
"cached": false
}
]
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
| next_page_token | string|null | Token to fetch the next page. Pass as pagetoken in the next request. null if no more pages. |
| results[].name | string | Business name. |
| results[].address | string | Formatted address. |
| results[].phone | string | Formatted phone number. |
| results[].website | string | Business website URL. |
| results[].rating | float | Average rating (1.0 – 5.0). |
| results[].rating_total | integer | Total number of reviews. |
| results[].types | string[] | Google Places type tags. |
| results[].weekday_text | string[] | Business hours for each day of the week. |
| results[].place_id | string | Unique Google Place ID (use with Reviews endpoint). |
| results[].business_status | string | OPERATIONAL, CLOSED_TEMPORARILY, or CLOSED_PERMANENTLY. |
| results[].cached | boolean | true if served from cache (0 credits), false if freshly fetched (10 credits). |
Pagination
Each request returns up to 20 results. If more results are available, the response includes a next_page_token. To fetch the next page:
curl "https://leadgen.tools/v2/api/v1/places/search.php?\ api_key=YOUR_KEY&\ user_id=123&\ keyword=restaurants+new+york&\ pagetoken=AeJbb3eFR..."
Google pagination delay: The next_page_token becomes valid after a short delay (~2 seconds). If you get an empty result immediately after, wait and retry.
Credit Calculation
- 10 credits per place that requires a fresh Google API lookup (cache miss).
- 0 credits for places already in cache (within 30 days).
- Typical first search: ~20 places × 10 credits = 200 credits.
- Subsequent same search: 0 credits (all cached).
Place Reviews
Fetch Google reviews for a specific place. Use the place_id from the Places Search response. Reviews are cached for 7 days.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| api_key Required | string | — | Your API key. |
| user_id Required | integer | — | Your user ID. |
| place_id Required | string | — | Google Place ID (e.g. ChIJr3_gqu5ZwokR...). Obtained from the Places Search endpoint. |
Example Request
curl "https://leadgen.tools/v2/api/v1/places/reviews.php?\ api_key=YOUR_KEY&\ user_id=123&\ place_id=ChIJr3_gqu5ZwokR..."
Example Response
{
"status": "success",
"credits_used": 5,
"data": {
"place_id": "ChIJr3_gqu5ZwokR...",
"reviews": [
{
"author_name": "John D.",
"author_url": "https://www.google.com/maps/contrib/...",
"language": "en",
"rating": 5,
"text": "Best pizza in NYC. Been coming here for 20 years!",
"time": 1705330200,
"relative_time_description": "a month ago",
"profile_photo_url": "https://lh3.googleusercontent.com/..."
}
],
"cached": false
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
| reviews | object[] | Array of review objects from Google. Up to 5 most relevant reviews (Google API limit). |
| reviews[].author_name | string | Reviewer's display name. |
| reviews[].rating | integer | Review rating (1 – 5). |
| reviews[].text | string | Review text content. |
| reviews[].time | integer | Unix timestamp of when the review was posted. |
| cached | boolean | true if served from cache (0 credits), false if freshly fetched (5 credits). |
Credit Calculation
- 5 credits for a fresh Google API call (cache miss).
- 0 credits if reviews are cached (within 7 days).
- If the Google API returns an error, 0 credits are deducted and an error response is returned.
Quick Reference
All endpoints at a glance:
Lead Search
Search engines for leads with email & phone extraction.
GET /api/v1/search.phpWebsite Crawler
Deep-crawl a website for contact data & social links.
GET /api/v1/crawl.phpAd Spy
Monitor ads with historical tracking & crawl enrichment.
GET /api/v1/ads.phpPlaces Search
Google Places business listings with full details.
GET /api/v1/places/search.phpPlace Reviews
Fetch Google reviews for any place by ID.
GET /api/v1/places/reviews.phpCredit Summary
| Endpoint | Method | Path | Credits | Cache TTL |
|---|---|---|---|---|
| Lead Search | GET | /api/v1/search.php | 0 – 10 | 7 days |
| Website Crawler | GET | /api/v1/crawl.php | 0 – 15 | 14 days |
| Ad Spy | GET | /api/v1/ads.php | 0 – 10 | Permanent (ads) / 7d (crawl) |
| Places Search | GET | /api/v1/places/search.php | 0 – 200 | 30 days |
| Place Reviews | GET | /api/v1/places/reviews.php | 0 or 5 | 7 days |
Changelog
v1.2 — February 2026
- Ad Spy — Historical ads: Ads are now stored permanently. Every search adds new ads to a historical database. Use
first_seen,last_seen, andis_activeto track ad lifespan and activity. - Ad Spy — Crawl enrichment: Each ad's landing page is automatically crawled for
emails,phones,social_links, and pagemetadata. Data is returned in thecontact_dataobject on each result. - Extended caching: Search cache increased from 1 hour to 7 days. Crawl cache increased from 24 hours to 14 days.
- New parameter:
include_historyon Ad Spy endpoint to control whether historical ads are included.
v1.1 — January 2026
- Places Search: Added Google Places Search endpoint with automatic caching.
- Place Reviews: Added Google Place Reviews endpoint with 7-day cache.
v1.0 — December 2025
- Initial release with Lead Search, Website Crawler, and Ad Spy endpoints.
- Softsale license key authentication.
- Credit-based billing with automatic caching.