Search companies
Lists companies matching the filters, best quality first unless you ask for another order. Rows spend your daily budget of companies, not your reveal quota. domain, website and contact stay null until you have revealed the company.
GEThttps://findbytown.com/api/v1/businessesNo quota
Parameters
| Name | Type | Description |
|---|---|---|
| country | string | Two-letter country code, such as FR. See GET /countries. |
| zone | string | Zone slug, such as fr_idf. See GET /zones. |
| city | string | Town name in any language: Cologne also finds Köln. |
| near | string | Radius search as lon,lat,km, up to 200 km. Only companies with a real location match. |
| nearName | string | Name of the place in near: companies with no exact location match when their own address names it. |
| postcode | string | Start of a postcode: 75011, or just 75 for all of them. Up to 4, separated by commas. |
| dept | string | French department code, such as 69 for the Rhône. |
| poly | string | Polygon as "lon lat" vertices separated by semicolons, 3 to 60 vertices. |
| q | string | Keywords, up to 6 words, matched across name, description, address and categories. A domain matches only when typed whole. |
| category | string | Broad category slug. See GET /categories. |
| trade | string | Trade key, a family of related categories. See GET /categories. |
| gcat | string | One exact listed category, ignoring case. |
| provider | own_smtp | google | microsoft | yahoo | invalid | unknown | Mail provider family of the company. |
| providerDetail | string | Exact mail provider name, ignoring case. |
| hasPhone | boolean | true: only companies with a phone number on file. |
| noPhone | boolean | true: only companies with no phone number on file. |
| hasContacts | boolean | true: only companies with named contacts. |
| noContacts | boolean | true: only companies with no named contacts. |
| hasOtherEmails | boolean | true: only companies with more than one email address. |
| qmin | integer | Lowest quality score, 0 to 100. |
| qmax | integer | Highest quality score, 0 to 100. |
| precision | string | Comma list of location precisions: exact, city, region, country. |
| approx | boolean | false: only companies with an exact location. Default true. |
| minRating | number | Lowest rating, 0 to 5. |
| minReviews | integer | Lowest number of reviews. |
| sizeClass | PME | ETI | GE | Registry size class. Registry facts are only known for some French companies. |
| headcount | string | One registry headcount band as stored, such as 20-49. |
| minHeadcount | integer | Lowest registry headcount: a company counts from the bottom of its band. |
| minRevenue | number | Lowest registry revenue, in euros. |
| legalForm | string | Registry legal form, ignoring case. |
| sort | quality | distance | rating | reviews | Order of results. distance needs near. |
| bbox | string | Map box as minLng,minLat,maxLng,maxLat. |
| page | integer | Page number, from 1. The last page you can reach is in maxPage. |
| perPage | integer | Rows on a page. A larger number is read as the maximum, and the response says which applied. |
| locale | en | fr | es | Language of labels and category names: en, fr or es. Defaults to the language of your account. |
Examples
curl "https://findbytown.com/api/v1/businesses?country=FR&trade=plumber&perPage=1" \
-H "Authorization: Bearer fbt_EXAMPLE_not_a_real_key_0000"const res = await fetch("https://findbytown.com/api/v1/businesses?country=FR&trade=plumber&perPage=1", {
headers: { Authorization: "Bearer fbt_EXAMPLE_not_a_real_key_0000" },
});
const body = await res.json();
if (!res.ok) throw new Error(body.error);
console.log(body);import requests
res = requests.get(
"https://findbytown.com/api/v1/businesses?country=FR&trade=plumber&perPage=1",
headers={"Authorization": "Bearer fbt_EXAMPLE_not_a_real_key_0000"},
)
body = res.json()
if not res.ok:
raise RuntimeError(body["error"])
print(body)Response
Example with fake values:
{
"data": [
{
"id": 1001,
"name": "Example Plumbing",
"domain": null,
"website": null,
"revealed": false,
"zone": "fr_idf",
"country": "FR",
"precision": "exact",
"quality": 80,
"provider": "google",
"providerDetail": "Google Workspace",
"hasPhone": true,
"hasEmail": true,
"contactsCount": 1,
"otherEmailsCount": 0,
"city": "Exampleville",
"adminArea": "Example Region",
"postalCode": "00000",
"address": "1 Example Street",
"fullAddress": "1 Example Street, 00000 Exampleville",
"activity": "Plumber",
"category": "Plumber",
"categories": [
"Heating contractor"
],
"websiteTitle": null,
"description": "Plumbing and heating repairs.",
"mapsUrl": null,
"rating": 4.6,
"reviews": 25,
"distanceM": null,
"facts": null,
"contact": null
}
],
"page": 1,
"perPage": 1,
"total": 128,
"maxPage": 200,
"hasMore": true,
"capped": false
}Errors
| Code | HTTP status | Meaning |
|---|---|---|
| validation_error | 400 | A parameter is missing or has the wrong form. details names it. |
| unknown_parameter | 400 | A query parameter is not one this endpoint knows, usually a typing mistake. details names it. |
| use_reveal_endpoint | 400 | You sent reveal= on a read. Reads never spend quota: use the reveal endpoint. |
| missing_api_key | 401 | No Authorization header, or an empty one. |
| invalid_api_key | 401 | The key does not exist or has been revoked. |
| plan_without_api | 403 | The account's current plan does not include the API. Applies from the moment a plan ends. |
| suspended | 403 | The account is suspended. Its keys start working again if the suspension is lifted. |
| rate_limited | 429 | Too many requests this minute. Wait for the number of seconds in Retry-After. |
| budget_exhausted | 429 | You reached today's budget of distinct companies. Companies already seen today still pass. Retry-After says when it resets. |
| blocked | 429 | Access to company data is temporarily paused because of automated use, such as walking through ids. Retry-After gives the time left. Write to support if this is a mistake. |
| internal_error | 500 | Something went wrong on our side. Quote requestId when writing to support. |