> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.hellodata.ai/llms.txt.

# Market Search

The market search endpoint returns the properties inside an area. The area can be a radius around a point or a custom polygon. You can narrow the results with filters like year built, unit count or property type.

Use it to size up the supply around a subject property, pull every property in a submarket, or build your own comp set.

> **Warning**
>
> This endpoint has to be activated for your account and is billed at a higher rate. [Contact us](/docs/contact-us) to turn it on.

### Search within a radius of a property

**1. Get the property's coordinates.** Use [Property Search](/docs/property-search) to find the property, or call `GET /property/{id}` if you already have its ID. Both return `lat` and `lon`.

**2. Search around it.** Send the coordinates and the radius in miles (up to 25).

#### Curl

```bash
curl --location 'https://api.hellodata.ai/market/search' \
--header 'x-api-key: your-api-key' \
--header 'Content-Type: application/json' \
--data '{
  "radius": { "lat": 41.8868, "lon": -87.6374, "miles": 1 }
}'
```

#### Python

```python
import requests

url = "https://api.hellodata.ai/market/search"

payload = {
    "radius": {"lat": 41.8868, "lon": -87.6374, "miles": 1}
}

headers = {
    "x-api-key": "your-api-key",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

for p in response.json()["properties"][:10]:
    print(f'{p["distance_miles"]:.2f} mi  {p["street_address"]}  ({p["number_units"]} units)')
```

#### JS

```javascript
const axios = require('axios')

const config = {
    method: 'post',
    url: 'https://api.hellodata.ai/market/search',
    headers: {
        'x-api-key': 'your-api-key',
        'Content-Type': 'application/json'
    },
    data: {
        radius: { lat: 41.8868, lon: -87.6374, miles: 1 }
    }
}

axios(config)
    .then((response) => {
        response.data.properties.slice(0, 10).forEach((p) => {
            console.log(p.distance_miles.toFixed(2), p.street_address, p.number_units)
        })
    })
    .catch((error) => {
        console.log(error)
    })
```

Results are sorted from closest to farthest, and each property includes `distance_miles`:

**`Market Search Response`**

```json Market Search Response
{
    "properties": [
        {
            "id": "15599d82-be17-5b45-8003-0738de431104",
            "lat": 41.88761,
            "lon": -87.63816,
            "building_name": "Wolf Point West",
            "street_address": "343 West Wolf Point Plaza",
            "city": "Chicago",
            "state": "IL",
            "zip_code": "60654",
            "year_built": 2015,
            "number_units": 529,
            "distance_miles": 0.07
        }
    ]
}
```

> **Info**
>
> In dense downtowns, even a 1 mile radius can have more than 2,500 properties, which is the most a request returns. With a radius you always get the closest ones. Check the last property's `distance_miles` to see how far the results actually reach, and add filters if you need the full radius.

### Narrow the results with filters

Add filters to the same request to keep only the properties you care about. Range filters take `min`, `max` and `allow_null`. Set `min` or `max` to `null` to leave that side open. `allow_null: true` keeps properties where we don't have that value.

This example keeps buildings built since 2010 with 100 to 400 units, and leaves out student and senior housing:

#### Curl

```bash
curl --location 'https://api.hellodata.ai/market/search' \
--header 'x-api-key: your-api-key' \
--header 'Content-Type: application/json' \
--data '{
  "radius": { "lat": 41.8868, "lon": -87.6374, "miles": 1 },
  "year_built": { "min": 2010, "max": null, "allow_null": false },
  "number_units": { "min": 100, "max": 400, "allow_null": false },
  "is_student": false,
  "is_senior": false
}'
```

#### Python

```python
payload = {
    "radius": {"lat": 41.8868, "lon": -87.6374, "miles": 1},
    "year_built": {"min": 2010, "max": None, "allow_null": False},
    "number_units": {"min": 100, "max": 400, "allow_null": False},
    "is_student": False,
    "is_senior": False,
}

response = requests.post(url, json=payload, headers=headers)
```

You can also filter by number of stories, unit mix (unit counts, size and rent by bedroom type), amenities, building quality and review score. See the [API Reference](/api-reference/api-reference/market/search) for the full list.

### Search inside a named market

To search a city, ZIP code, neighborhood or MSA, look up its boundary with `GET /market/shape_search` and send it as `coordinates`. Shape search is free.

#### Python

```python
import requests

headers = {"x-api-key": "your-api-key"}

markets = requests.get(
    "https://api.hellodata.ai/market/shape_search",
    headers=headers,
    params={"q": "West Loop Chicago"},
).json()

for m in markets:
    print(m["name"], m["tags"])  # pick the one you want

market = markets[0]

response = requests.post(
    "https://api.hellodata.ai/market/search",
    headers={**headers, "Content-Type": "application/json"},
    # shape_search returns a single ring, so wrap it as one polygon
    json={"coordinates": [[market["coordinates"]]]},
)
```

Shape search returns up to 7 matches. Check `name` and `tags` before you use one, because a query like "Springfield" matches more than one place.

### Search inside a custom area

If you have your own boundary, send it as `coordinates`. The format follows GeoJSON: a list of polygons, each a list of rings, each a list of `[longitude, latitude]` pairs. The first ring is the outline and any others are holes.

```json
{
  "coordinates": [[[[-87.65, 41.87], [-87.62, 41.87], [-87.62, 41.90], [-87.65, 41.90], [-87.65, 41.87]]]]
}
```

> **Info**
>
> Coordinates are `[longitude, latitude]`, in that order. Swapping them is the most common reason a search comes back empty.

Send either `radius` or `coordinates`, not both.

### Limits

* Each request returns at most **2,500 properties**.
* With `radius`, those are the 2,500 closest. With `coordinates`, they are **not** in any useful order. If a polygon search returns exactly 2,500, split the area into smaller searches or add filters, and combine the results by `id`.
* The maximum radius is 25 miles.
* Each request is billed as one market search call, however many properties it returns.

### Full Documentation

Find every filter and response field in the [API Reference](/api-reference/api-reference/market/search).