# Roof Measurement API - Area, Pitch, Condition, Hail Risk (`nabeelbaghoor/roof-measurement-condition-api`) Actor

Measure any US property from aerial imagery: roof area, roofing squares, pitch, eave height, material, shape and estimated age, a five point condition rating with the ponding, rust, tarp and patching findings behind it, pools, trampolines, fences and debris, plus wildfire and hail risk scores.

- **URL**: https://apify.com/nabeelbaghoor/roof-measurement-condition-api.md
- **Developed by:** [Nabeel Hassan](https://apify.com/nabeelbaghoor) (community)
- **Categories:** Real estate, Business, Other
- **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 record 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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Roof Measurement API - Area, Pitch, Condition, Hail Risk

Measure and assess any US property from aerial imagery: roof area and roofing squares, pitch, eave height, material, shape, facet count and estimated age, a five point roof condition rating with the specific defects behind it, and wildfire and hail vulnerability scores - every reading with the model confidence that qualifies it.

### What this actor does

- **Roof measurements without climbing on the roof.** Three dimensional roof area in square feet and in roofing squares, predominant pitch expressed over 12, eave height measured in four cardinal directions, footprint, facet count and roof shape. This is the estimate that goes into a restoration bid before anyone sets a ladder against the wall.
- **A roof condition rating you can argue with.** The headline rating runs compromised, poor, fair, good, excellent - and every sub-element behind it comes back as its own column: ponding, patching, tarps, rust, structural damage, missing or peeling material, streaking, natural discoloration, material degradation and loose organic matter. A "poor" with rust and a "poor" with ponding are different repairs, and this tells them apart.
- **Estimated roof age.** Years, from aerial history and property records, for underwriting and replacement planning.
- **Wildfire and hail vulnerability scores with their reasons.** Numeric ratings for both hazards, the post-mitigation wildfire rating, hail loss severity, and the structure counts, densities and vegetation coverage in the two concentric zones around the building - 0 to 30 feet and 30 to 250 feet - that drive defensible space decisions.
- **Property features an underwriter asks about.** Pool presence, count, condition, type, occlusion, slide, diving board and enclosure; trampolines; fences and whether the fence material is combustible; lot and yard debris area and coverage; driveway and lawn condition; HVAC unit counts; parking lot paved area with deterioration and illumination.
- **One row per structure, not one per property.** A house, a detached garage and a shed are three buildings with three roofs in three conditions. They arrive as three rows, joined by the address you asked for, instead of being averaged into one number that describes none of them.
- **Screen a list cheaply before you analyse it.** Property summary mode reads the headline roof condition, primary material and solar panel presence for twenty addresses in a single call, so a portfolio can be triaged before spending on full analyses.
- **The imagery behind the answer.** Rank the aerial captures over a point - top down and all four angled views - with capture dates, ground sample distance, zoom range and whether the image is a composite stitched from several frames. Search stitched orthomosaic imagery over an area by spectrum, positioning quality and capture window.
- **Pay per result.** You are charged for rows carrying a real record. Addresses the provider cannot geocode and locations with no capture are free.

### Bring your own key

This actor calls the provider with **your own application credentials**, issued in the provider's developer portal. Access is an OAuth2 client credentials grant, so there are **two** values rather than one: a client ID and a client secret. Paste both into the input, or set the secret as the `DATA_API_KEY` secret. Nothing runs on anyone else's credentials, and a run without them ends cleanly with an explanation rather than failing.

The actor mints a bearer token, caches it for 55 minutes of its one hour life, and re-mints it once if a long run outlives it. A pasted `Bearer ` or `Basic ` prefix is stripped, so copying the whole header line instead of the value still works.

### Try it free in the sandbox first

The provider runs a free sandbox that mirrors production behaviour over about **1.5 square miles of Omaha, Nebraska**. Turn on *Use the free sandbox* and query an address inside that area - for example `4220 Barker Ave, Omaha, NE 68105` - to confirm your credentials and see the shape of the output before spending anything.

Outside that box the sandbox returns nothing. That is a correct answer to a question nobody meant to ask, so this actor says so on the row rather than reporting it as a provider failure, and it refuses an out-of-box coordinate before spending the call at all.

### Every number arrives with a confidence

Nothing this provider returns is a bare value. A roof area is `{value, unit, confidence}`; so is a condition rating, a hazard score and a pool detection. A shaper that reads only the value silently turns a hedged computer vision reading into an apparent fact.

So each reading is written as its own columns - the value, its unit, and the model confidence - and the confidence sits beside the number it qualifies. When the model supplies reasons, as it does for the wildfire and hail ratings, those travel too. On a vision-derived measurement the confidence is half the answer.

### Data packs are licensed one at a time

The provider sells its data in packs - roof area, pitch and eave height, material and condition, roof age, property condition, risk scores, building outlines, ortho imagery, oblique imagery - and your application is entitled to the ones you bought.

Two things follow. Leaving *Data packs* empty returns whatever your application already holds, which is usually what you want. And naming a pack you do not hold gets the **whole request rejected** rather than trimmed to what you do hold, so the actor reports that case as an entitlement problem naming the packs it asked for, instead of as a generic forbidden error.

### Example output

```json
{
  "recordType": "structure",
  "requested": "4220 Barker Ave, Omaha, NE 68105",
  "requestedKind": "address",
  "found": true,
  "structureIndex": 1,
  "structureLatitude": 41.25042,
  "structureLongitude": -95.97661,
  "roofArea": 2184.6,
  "roofAreaUnit": "sqft",
  "roofAreaConfidence": 0.93,
  "roofSquares": 22,
  "roofPredominantPitch": 6,
  "roofShape": "gable",
  "roofMaterialPrimary": "shingle",
  "roofMaterialPrimaryConfidence": 0.88,
  "roofConditionRating": "fair",
  "roofConditionRatingConfidence": 0.81,
  "roofAge": 14,
  "roofPonding": "no",
  "roofPatching": "yes",
  "roofStreaking": "roof_streaking_minor",
  "roofFacetCount": 8,
  "eaveHeight": "{\"north\":10.2,\"east\":10.4,\"south\":10.1,\"west\":10.3}",
  "eaveHeightUnit": "ft",
  "treeOverhang": "tree_overhang_minor",
  "structureHailRating": 6.2,
  "structureWildfireRating": 3.1,
  "structureWildfireRatingReasons": "vegetation within 30 ft; combustible fence",
  "structureCountZone1": 1,
  "structureCountZone2": 14
}
```

### FAQ

#### What does this Roof Measurement API return?

Roof measurements and condition for a US property, derived from aerial imagery: three dimensional roof area in square feet and roofing squares, predominant pitch over 12, eave height by cardinal direction, roof shape, facet count, primary material and full material list, estimated roof age in years, and a five point condition rating backed by per-defect findings for ponding, patching, tarps, rust, structural damage, missing material, streaking, discoloration and material degradation. It also returns property-level features and wildfire and hail vulnerability scores.

#### How accurate are the measurements, and how do I tell?

Every measurement and classifier carries a model confidence between 0 and 1 in its own column beside the value, so a reading you can rely on is distinguishable from one the model hedged. Measurements are computer-vision estimates from aerial imagery rather than survey-grade figures, and the ground sample distance of the underlying imagery is available through the imagery modes. For the wildfire and hail ratings the model also returns the ranked reasons behind the score.

#### Do I need my own account with the data provider?

Yes. This is a bring-your-own-key actor: it calls the API with your own application's client ID and client secret from the provider's developer portal, and never with anyone else's. The provider also offers a free sandbox covering about 1.5 square miles of Omaha, Nebraska, which is the fastest way to confirm a credential works before spending anything.

#### What is the difference between property data and property summary mode?

Property data analyses one property in full and returns a property row, a row for each structure on it, and optionally a row for each aerial image behind it. Property summary screens up to twenty addresses in a single call and returns only the headline roof condition rating, primary roof material and solar panel presence for each. Summary is the cheap triage pass over a portfolio; property data is the detailed look at the addresses that pass it.

#### Why does a property produce several rows?

Because a property is usually several buildings. A house, a garage and a shed have three separate roofs that can be in three different conditions, and averaging them produces a number that describes none of them. Each structure gets its own row, keyed to the address you requested and numbered, alongside one property-level row for the things that belong to the lot rather than to a building.

#### How long does a request take?

Analysis is asynchronous. The actor submits the request, receives a job identifier and polls until the job finishes, which the provider signals by answering with the result rather than with an in-progress status. Typical properties complete in seconds; the actor polls for up to six minutes before treating the job as failed rather than as empty.

#### Can I get the aerial images themselves?

The actor returns image metadata and a ready download link per image - the reference, the token, whether the view is top down or angled, the cardinal direction, the capture date and the bounding box. The image bytes are not written into the dataset, because a spreadsheet full of encoded pictures is unusable; follow the link with the same credentials to fetch the file.

#### Which US areas are covered?

Coverage follows the provider's aerial imagery library, which is national but not uniform: capture dates and ground sample distance vary by location. Imagery capture mode answers that question directly for any point, listing every capture over it with its date and resolution, so you can check coverage before ordering analysis.

### Keyword map

roof measurement API, roof report API, roof area API, roofing squares, roof pitch API, roof condition API, roof age API, roof material detection, aerial imagery API, property condition API, property data API, property intelligence API, insurance underwriting data, wildfire risk score API, hail damage risk API, defensible space data, pool detection API, trampoline detection, solar panel detection API, orthomosaic imagery API, oblique aerial imagery, geospatial property data, roof inspection data, restoration estimating data, property risk API

# Actor input Schema

## `mode` (type: `string`):

Property data reads one property in full: every structure, its roof measurements and condition, the hazards around it and the imagery behind them. Property summary reads the headline roof condition, material and solar panel presence for up to twenty addresses per call, which is the cheap way to screen a list. Property attributes reads the older near real time attributes service. Imagery captures ranks the aerial captures over a point, and orthomosaic search finds stitched imagery over an area.

## `targets` (type: `array`):

One subject per line. A full street address including city, state and ZIP, or a "latitude,longitude" pair in that order. A line of two numbers is read as coordinates and anything else as an address.

## `street` (type: `string`):

Street line of a single structured address, used when the list above is empty. Pair it with the city, state and ZIP fields. A structured address geocodes more reliably than a single line when the address is unusual.

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

City of the structured address.

## `state` (type: `string`):

Two letter state code of the structured address, for example NE.

## `zip` (type: `string`):

Postal code of the structured address.

## `country` (type: `string`):

Two letter country code of the structured address. Defaults to US.

## `productIds` (type: `array`):

Which licensed data packs to ask for. Leave empty to get whatever your application is already entitled to. Packs are licensed individually and a request naming one you do not hold is rejected whole rather than trimmed, so ask only for packs you have.

## `includeStructures` (type: `boolean`):

Emit one row for each structure on the property, carrying its roof measurements, materials, condition sub-elements and the hazard zones around it. A property with a house, a garage and a shed produces three rows rather than one blended one.

## `includeImages` (type: `boolean`):

Emit one row for each aerial image behind the analysis, with its token, view, capture date, cardinal direction and a download link. Off by default because the rows are metadata about pictures rather than property data.

## `polygonWkt` (type: `string`):

An area of interest for the imagery modes, written as WKT in EPSG:4326, for example POLYGON((-95.98608 41.25056, -95.98608 41.2502, -95.98555 41.2502, -95.98555 41.25056, -95.98608 41.25056)). Takes precedence over the coordinates above.

## `radiusMeters` (type: `integer`):

How far around the point to search in the imagery modes. Capture ranking is capped by the provider at 75 metres and larger values are clamped to it; orthomosaic search has no such cap and defaults to 100.

## `maxImagesPerView` (type: `integer`):

How many images to return for each view in capture ranking. The provider defaults to one, which is the best image for that view.

## `maxGsdMeters` (type: `number`):

Only consider imagery at or below this ground sample distance in metres per pixel. A smaller number is sharper imagery, for example 0.075.

## `compositeRequirement` (type: `string`):

Composite images are stitched from several frames taken at different moments, so their capture time is approximate. Choose whether to accept them, require them or exclude them.

## `capturedSince` (type: `string`):

Only consider imagery captured on or after this date, as YYYY-MM-DD.

## `capturedUntil` (type: `string`):

Only consider imagery captured on or before this date, as YYYY-MM-DD.

## `orthomosaicCategories` (type: `array`):

Limit orthomosaic search to visible light imagery, near infrared imagery, or both. Leave empty for the provider's default.

## `orthomosaicLevels` (type: `array`):

Limit orthomosaic search by how the imagery was positioned. Georegistered is geographically placed, aerial triangulated is refined against matching points across images, and measured is anchored to surveyed ground control points. They differ in absolute accuracy, which matters if you measure off the image.

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

Intersects returns imagery that overlaps the area at all. Contains returns only imagery that covers the whole area, which is what you want when a partial image would be useless.

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

How many orthomosaics the provider returns per page, between 1 and 100. Paging continues automatically until the row cap is reached.

## `clientId` (type: `string`):

Your own application's client ID from the provider's developer portal. Access is a two part credential: this and the client secret are sent together, so one of the two being wrong looks exactly like both being wrong.

## `clientSecret` (type: `string`):

Your own application's client secret from the provider's developer portal. Stored encrypted and never written into the dataset. Can also be supplied as the DATA\_API\_KEY environment secret.

## `useSandbox` (type: `boolean`):

Call the provider's free sandbox instead of production. The sandbox mirrors production behaviour but only holds about 1.5 square miles of Omaha, Nebraska, so anything outside that area comes back empty. Useful for checking your credentials work before spending anything.

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

Stop after this many rows. Counts every row: properties, structures, images and imagery records alike.

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

How fast to call the provider. Lower this if your plan's rate limit is being hit.

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

Overrides the host the data endpoints are called on. Leave empty unless the provider has given you a different one.

## `tokenBaseUrl` (type: `string`):

Overrides the host the access token is minted on. Tokens always come from the production host, in sandbox and production alike, and it is a different host from the data endpoints by design, which is the most common cause of a 404 that looks like a bad credential. Leave empty unless the provider has given you a different one.

## `legacyBaseUrl` (type: `string`):

Overrides the host the older property attributes service is called on. It is a different host from the other data endpoints, and it is the one the sandbox actually moves. Leave empty unless the provider has given you a different one.

## Actor input object example

```json
{
  "mode": "propertyData",
  "country": "US",
  "includeStructures": true,
  "includeImages": false,
  "compositeRequirement": "",
  "spatialOperation": "",
  "pageSize": 10,
  "useSandbox": false,
  "maxResults": 100,
  "requestsPerMinute": 60
}
```

# Actor output Schema

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

One row per record, alongside the address or coordinate 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/roof-measurement-condition-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/roof-measurement-condition-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/roof-measurement-condition-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nabeelbaghoor/roof-measurement-condition-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/kJlVjf6kyo7PkhB8C/builds/7RSUZwUot2KopgckE/openapi.json
