# Aerial Imagery API - Roof, Pool and Damage Data (`nabeelbaghoor/aerial-imagery-property-api`) Actor

Property data derived from aerial imagery: roof material, condition grade, solar panels, footprint and height, pools, decks, trampolines, sport courts, vehicles and tree cover, post-catastrophe damage with FEMA classification, plus imagery coverage, capture dates and elevation.

- **URL**: https://apify.com/nabeelbaghoor/aerial-imagery-property-api.md
- **Developed by:** [Nabeel Hassan](https://apify.com/nabeelbaghoor) (community)
- **Categories:** Real estate, Business, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 1,000 property or structure returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Aerial Imagery API - Roof, Pool and Damage Data

Find out what is on a property without visiting it, from aerial imagery flown at seven and a half centimetres.

### What it collects

- **Roof facts**: material, condition grade on the provider's one to five scale, detected solar panels, roof area, footprint area and building height, for the primary structure and for every other building on the parcel.
- **Parcel features**: swimming pool with its type, area and whether it has a hot tub, diving board or water slide, plus decks, trampolines, sport courts, playgrounds, enclosures, vehicles, boats, tree cover percentage and hardscape percentage.
- **Damage assessment** after a catastrophe: condition before and after the event, the catastrophe score, the FEMA damage classification, and per-structure condition where more than one building was assessed.
- **Imagery coverage**: which orthomosaic and oblique imagery exists over a location, which programme flew it, its first and last capture dates and its ground sample distance range.
- **Capture dates**: when an area was last flown, so you know how old the derived data actually is.
- **Elevation**: your own geometry returned with a height on every coordinate, from either the surface model, which includes buildings and trees, or the terrain model, which is bare ground.
- **Counts**: how many parcels match your filters over an area, so you can size a job before committing to it.

### FAQ

#### What property data can aerial imagery give me?

Roof material, roof condition, solar panel presence, roof and footprint areas and building height for every structure on a parcel, plus pools with type and area, decks, trampolines, sport courts, playgrounds, enclosures, vehicles, boats, tree cover and hardscape percentages. All of it is computed from imagery rather than from public records, so it reflects what is physically there.

#### How do I find properties with a swimming pool or solar panels?

Run property attributes over a polygon and turn on the pool or roof solar filter. Both are detection filters applied by the provider before the rows come back, so you pay for matches rather than for everything in the area. Run the property count service first to see how many parcels match before collecting them.

#### Can I filter by roof condition?

Yes. Set a minimum or maximum roof condition and the provider returns only properties in that band. The grade is a one to five scale, and this actor keeps it exactly as the provider publishes it, never rescaled or inverted, because the provider does not state which end is good and inventing a direction would be worse than leaving it alone.

#### How fresh is the imagery behind the data?

Ask directly. The ortho capture dates service says when an area was last flown, and the coverage services return first and last capture dates with the ground sample distance for each collection. You can also restrict any query to imagery captured between two dates.

#### Does this actor consume my imagery credits?

No. Every route it calls reads metadata or derived data. Nothing here extracts an image, generates a bundle or orders a product, so a scheduled run cannot spend the credits those cost.

#### Why did my filter seem to do nothing?

It may not have been sent. This provider ignores a query parameter it does not recognise rather than refusing it, so a filter that a given service does not accept looks exactly like a filter that matched nothing. This actor drops those before the request and names each one in the run log, so an empty run is an explained one.

#### Are the measurements metric or imperial?

Whichever you choose, and the choice is recorded on every row. The provider takes a unit system per request and does not say in its response which one it used, so an area from this API that did not travel with its unit would not be a measurement at all. Elevation z values are metres regardless, as the provider documents, and the rows say so.

#### How do I give it a location?

One per line, either a "latitude,longitude" pair or a well known text geometry such as `POINT(-87.2095 30.4047)` or a `POLYGON`. Pairs are written latitude first, the way people write coordinates, and converted to the longitude-first order this API expects. The projection is always sent explicitly, because EPSG:4326 and EPSG:3857 put the same numbers in entirely different places.

#### Do I need my own API key?

Yes. This actor is bring-your-own-key and never ships a key of its own. It takes either an API key, sent in a header rather than in the query string so it does not end up in server logs, or your account username and password, which it exchanges for a session token.

#### What does it cost?

Pay per result. A property or damage row costs the most, elevation less, imagery coverage a fraction of that because finding out whether an area has been flown should be cheap, and a match count is priced near zero. Platform usage is included. Locations with no coverage are never charged.

### Example output

```json
{
  "recordType": "property",
  "requested": "30.404678,-87.209520",
  "found": true,
  "unitSystem": "metric",
  "srid": "4326",
  "structureCount": 1,
  "primaryStructureFootprintArea": 146.33,
  "primaryStructureRoofMaterial": "shingle",
  "primaryStructureRoofCondition": 4,
  "primaryStructureRoofSolar": false,
  "poolDetected": true,
  "poolAreaSqUnits": 48.22,
  "inGroundPool": true,
  "trampolineDetected": false,
  "deckDetected": false,
  "vehicleCount": 1,
  "boatCount": null,
  "treeCoverPercent": 15,
  "parcelSource": "real",
  "latitude": 30.404678,
  "longitude": -87.20952
}
```

### Keyword map

aerial imagery API, property intelligence API, roof condition data API, roof material detection, solar panel detection API, swimming pool detection data, property risk data for insurance, catastrophe damage assessment API, FEMA damage classification data, post-event imagery, building footprint API, building height data, DSM DTM elevation API, tree cover overhang data, underwriting property data, oblique oriented imagery metadata.

### Notes

Bring your own key. Read only: no route here extracts imagery or orders a product. Rate limiting, retries and paging are handled for you, and missing or refused credentials end the run cleanly with an explanation rather than failing it. This gateway checks the credential before it looks at the path, so a refusal cannot be told apart from an unknown path; the actor says so rather than asserting your key is wrong when it may be fine.

# Actor input Schema

## `service` (type: `string`):

Property attributes reads the parcel and building facts derived from aerial imagery. Structures reads each building on its own. Damage assessment reads post-catastrophe condition. The coverage services say which imagery exists over a location and when it was flown. The elevation services add a height to every coordinate you give them.

## `locations` (type: `array`):

One location per line, either a "latitude,longitude" pair or a well known text geometry such as POINT(-87.2095 30.4047) or POLYGON((...)). Pairs are written latitude first and converted to the longitude-first order this API expects, so a pair written the way people write coordinates cannot become a real place somewhere else. On the coverage services this is optional: leave it empty to read the whole catalogue your licence covers.

## `srid` (type: `string`):

Which projection your coordinates are in. This is always sent explicitly rather than left to a server default, because the same numbers land in entirely different places under the two.

## `layers` (type: `array`):

Which imagery programmes to read from. Urban is the highest resolution, wide area covers more ground at lower resolution, and graysky is flown after a catastrophe. The elevation and capture date services require at least one.

## `unitSystem` (type: `string`):

Which units areas, lengths and heights come back in. The provider does not say in its response which one it used, so whichever you pick is recorded on every row.

## `collection` (type: `string`):

Restrict to one named imagery collection, for example us-tx-pearland-2021. Leave empty to use whatever covers the location.

## `collectYear` (type: `integer`):

Restrict to imagery flown in this year, as four digits.

## `graySkyEvent` (type: `string`):

Restrict to imagery flown for one named catastrophe event, for the damage services.

## `captureDateFrom` (type: `string`):

Only use imagery first captured on or after this day, written as YYYY-MM-DD.

## `captureDateTo` (type: `string`):

Only use imagery last captured on or before this day, written as YYYY-MM-DD.

## `latestOnly` (type: `boolean`):

Read only the most recent imagery over each location rather than every capture the provider holds.

## `bufferMetres` (type: `integer`):

Widen each location by this many metres before searching. Useful when a point falls just outside the parcel you meant.

## `primaryStructureOnly` (type: `boolean`):

Return only the main building on each parcel, rather than sheds, garages and outbuildings as well.

## `minRoofCondition` (type: `integer`):

Only return properties whose roof condition grade is at least this. The provider grades from 1 to 5 and the grade is kept exactly as it publishes it, never rescaled or inverted.

## `maxRoofCondition` (type: `integer`):

Only return properties whose roof condition grade is no more than this, on the provider's 1 to 5 scale.

## `roofMaterial` (type: `array`):

Only return properties whose roof is made of one of these materials, as detected from the imagery.

## `hasPool` (type: `boolean`):

Only return properties with a swimming pool detected in the imagery.

## `hasSolar` (type: `boolean`):

Only return properties with solar panels detected on the roof.

## `hasTrampoline` (type: `boolean`):

Only return properties with a trampoline detected in the imagery.

## `hasDeck` (type: `boolean`):

Only return properties with a deck detected in the imagery.

## `hasSportCourt` (type: `boolean`):

Only return properties with a sport court detected in the imagery.

## `hasPlayground` (type: `boolean`):

Only return properties with playground equipment detected in the imagery.

## `hasEnclosure` (type: `boolean`):

Only return properties with an enclosure detected in the imagery.

## `hasBoat` (type: `boolean`):

Only return properties with a boat detected on the parcel.

## `minCatastropheScore` (type: `integer`):

Only return damaged properties scoring at least this, on the provider's own catastrophe scale.

## `maxCatastropheScore` (type: `integer`):

Only return damaged properties scoring no more than this.

## `minFemaClassification` (type: `integer`):

Only return damaged properties at or above this FEMA damage classification.

## `maxFemaClassification` (type: `integer`):

Only return damaged properties at or below this FEMA damage classification.

## `spatialOperation` (type: `string`):

How a coverage area has to relate to your geometry to count. Intersect returns anything overlapping it; covers returns only coverage containing all of it; within returns only coverage entirely inside it.

## `orientationSource` (type: `string`):

Which imagery the structure measurements are taken from, for the structures service.

## `productType` (type: `string`):

Restrict to one of the provider's ortho or oriented product types. Leave empty for the default product.

## `bands` (type: `string`):

Which spectral bands to read for oriented image metadata. Infrared is only available where it was flown.

## `include` (type: `string`):

A comma separated list of extra fields to include, in the provider's own naming, for example first-capture-date,last-capture-date,min-gsd. Leave empty for the default field set.

## `includeGeometry` (type: `boolean`):

Adds the full GeoJSON footprint or coverage polygon to each row. Off by default because a polygon makes a spreadsheet cell enormous without making it useful, and every row already carries a centre point.

## `pageSize` (type: `integer`):

How many records to ask for per request on the services that page.

## `maxResults` (type: `integer`):

Stop after this many rows. Counts every row the run collects.

## `requestsPerMinute` (type: `integer`):

How fast to call the provider. The default of 60 is one a second, which is polite for a metered imagery API. Raise it if your licence allows more.

## `apiKey` (type: `string`):

Your own account key, issued by the provider. Sent in an X-API-KEY header rather than in the query string, so it does not end up in server logs, proxy logs or browser history. Stored encrypted and never written into the dataset. Can also be supplied as the DATA\_API\_KEY environment secret.

## `username` (type: `string`):

Your own account username, for accounts issued a login rather than an API key. Exchanged with the password below for a session token. Leave empty if you have a key.

## `password` (type: `string`):

The password for the username above. Stored encrypted and never written into the dataset. Leave empty if you have a key.

## `baseUrl` (type: `string`):

Overrides the host the API is called on. Leave empty unless the provider has given you a different one.

## Actor input object example

```json
{
  "service": "propertyAttributes",
  "srid": "4326",
  "unitSystem": "metric",
  "latestOnly": true,
  "primaryStructureOnly": false,
  "hasPool": false,
  "hasSolar": false,
  "hasTrampoline": false,
  "hasDeck": false,
  "hasSportCourt": false,
  "hasPlayground": false,
  "hasEnclosure": false,
  "hasBoat": false,
  "spatialOperation": "",
  "orientationSource": "",
  "bands": "",
  "includeGeometry": false,
  "pageSize": 100,
  "maxResults": 100,
  "requestsPerMinute": 60
}
```

# Actor output Schema

## `records` (type: `string`):

One row per record, alongside the location that produced it.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("nabeelbaghoor/aerial-imagery-property-api").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("nabeelbaghoor/aerial-imagery-property-api").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 '{}' |
apify call nabeelbaghoor/aerial-imagery-property-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nabeelbaghoor/aerial-imagery-property-api"
        }
    }
}
```

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/SNcucGRh53vTIH7cq/builds/0VPBB0WcuzLlM0RkF/openapi.json
