AI Drone Roof Inspection Report — Findings & Repair Scope avatar

AI Drone Roof Inspection Report — Findings & Repair Scope

Pricing

from $20.00 / 1,000 photo analyzed (hosted, fast tier)s

Go to Apify Store
AI Drone Roof Inspection Report — Findings & Repair Scope

AI Drone Roof Inspection Report — Findings & Repair Scope

Turn drone and ground roof photos into a per-building inspection report: defect findings per photo, condition grade, repair scope, materials and labor from your price list, a Markdown report and contact sheet. Rules mode or Claude vision. Pay per photo and per building.

Pricing

from $20.00 / 1,000 photo analyzed (hosted, fast tier)s

Rating

0.0

(0)

Developer

Owlabee

Owlabee

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Categories

Share

What it does

AI Drone Roof Inspection Report turns a set of roof photos into a preliminary, per-building inspection report that an estimator can price and a field crew can verify. Give it drone or ground photos (image URLs, kvs://<storeId>/<key> references to an Apify key-value store, or data: URLs) and it:

  1. reads each photo's EXIF (capture time, GPS position, camera make and model) and numbers the photos in input order (Photo 1, Photo 2…);
  2. groups the photos into buildings: by your own labels when you give them ("Building 12": "1-7, 158"), otherwise by GPS distance, otherwise by gaps in capture time;
  3. in model modes, sends each photo (downscaled to at most 1120x840 pixels) to Claude vision, which returns per-photo defect findings: defect type (missing, lifted, creased or torn shingles, granule loss, exposed mat or decking, flashing, chimney, pipe boot or vent, ridge and hip cap, ponding, membrane, debris, gutters, prior repairs), severity, location on the roof, quantity, confidence and the photo number;
  4. writes one building rollup per roof: roof type, condition grade (good, fair, poor, end-of-life), replacement priority (1 = within 12 months, 2 = within 24, 3 = within 36, 4 = not indicated), observations that cite photo numbers, and a repair scope in zones, linear feet and each;
  5. turns the scope into materials in whole packs, a labor bundle and a height charge with deterministic code (no model) using your price list, or a built-in EXAMPLE price list that you must replace with your own;
  6. saves a Markdown report (REPORT), a JPEG contact sheet of the first 100 photos labeled with their numbers (CONTACT_SHEET) and a run summary (SUMMARY) to the key-value store.

Every quantity carries verificationRequired: true, and the report states that counts are taken from photographs and will be verified on the roof.

Three analyzers, chosen with the analyzer input and recorded on every item as analysisMethod:

  • hosted (default when the Actor's model key is configured): Claude on the Actor's own key, tokens included, from $0.02 per photo plus $0.10 per building. Pick a model tier: fast (Claude Haiku 5.5) or balanced (Claude Sonnet 5.5); the best tier (Claude Opus 5.5) is available with your own key (byok).
  • byok (bring your own key): the same analysis with the anthropicApiKey you supply; $0.01 per photo and $0.05 per building here, tokens billed by Anthropic to you.
  • rules: no model. EXIF index, building grouping and contact sheet, with empty findings, for $0.002 per photo; the building items are free in this mode because they are an index without findings. This is what Apify's daily test runs.

Built for roofing contractors, property managers and multifamily owners, insurance-restoration estimators and drone service providers who need to go from a few hundred photos to a building-by-building scope quickly. Results are available as JSON, CSV, Excel, through the API, webhooks and the Apify MCP server.

How to use

  1. Paste your Roof photo URLs, one per line, in the order you want them numbered. Optionally add Building labels ([{"label": "Building 1", "photos": "1-12", "stories": 2}]) and your Price list and Company and property details.
  2. Leave Analyzer empty for hosted Claude vision and pick a Model tier (fast is the default); or choose byok and paste your Anthropic API key; or choose rules for a model-free photo index.
  3. Click Start. Photo items and building items appear in the dataset as they are ready; open REPORT and CONTACT_SHEET in the key-value store (Output tab) when the run finishes.

Quick start input

The same input the Store runs in its daily automated test, so it is cheap and always available; paste it into the JSON tab of the input form or send it as the body of an API or MCP call:

{
"imageUrls": [
"https://upload.wikimedia.org/wikipedia/commons/thumb/c/c8/US_Navy_070706-N-3832S-057_Cyptologic_Technician_Technical_1st_Class_Jason_Guidry_nails_shingles_onto_the_roof_of_a_house_during_a_community_relations_project_with_Habitat_for_Humanity.jpg/960px-US_Navy_070706-N-3832S-057_Cyptologic_Technician_Technical_1st_Class_Jason_Guidry_nails_shingles_onto_the_roof_of_a_house_during_a_community_relations_project_with_Habitat_for_Humanity.jpg",
"https://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/US_Navy_090611-N-9712C-001_Aviation_Electronics_Technician_2nd_Class_Sonny_Abernathy_nails_shingles_to_the_roof_of_a_Habitat_for_Humanity_house.jpg/960px-US_Navy_090611-N-9712C-001_Aviation_Electronics_Technician_2nd_Class_Sonny_Abernathy_nails_shingles_to_the_roof_of_a_Habitat_for_Humanity_house.jpg",
"https://upload.wikimedia.org/wikipedia/commons/thumb/f/ff/Staggered_planks_on_the_roof_referred_to_as_%22skip_sheathing%22_forms_the_surface_for_new_cedar_shingles_to_be_attached_to_the_roof._%283d6d81ed-74ae-4577-b77a-8f05e2b5c48b%29.jpg/960px-Staggered_planks_on_the_roof_referred_to_as_%22skip_sheathing%22_forms_the_surface_for_new_cedar_shingles_to_be_attached_to_the_roof._%283d6d81ed-74ae-4577-b77a-8f05e2b5c48b%29.jpg"
],
"analyzer": "rules"
}

Input

FieldTypeRequiredDescription
imageUrlsstring[]yesPhoto URLs, kvs://<storeId>/<key> references or data: URLs, one per line; the first is Photo 1
buildingsobject[]noBuilding labels: { label, photos ("1-7, 158"), stories, units }. Unlabeled photos are grouped by GPS, then by time
analyzerstringnohosted, byok or rules. Empty = hosted when the Actor's model key is configured, else rules
anthropicApiKeystring (secret)for byokYour Anthropic API key; used only in byok mode
modelTierstringnofast (default, Claude Haiku 5.5) or balanced (Claude Sonnet 5.5) in hosted mode; byok also takes best (Claude Opus 5.5)
instructionsstringnoExtra guidance for the model: roof system, what to ignore, local terminology. Ignored by rules
priceListobjectnomaterials [{name, packSize, perUnit, appliesTo, priceUsd}], laborBundles [{hours, priceUsd}], heightCharges [{stories, priceUsd}], laborRounding ('down' default or 'up'), hoursPerZone, zoneSf, currency. Empty = the EXAMPLE list (placeholder prices)
companyobjectnoReport header: name, email, phone, website, inspector, propertyName, propertyAddress, inspectionDate
maxPhotosintegernoPhotos processed per run, 1–500 (default 200)
photosPerModelCallintegernoPhotos of one building per model call, 1–8 (default 4)
groupingDistanceMetersnumbernoGPS grouping radius, 5–500 m (default 25)
groupingGapMinutesnumbernoTime gap that starts a new building when there is no GPS, 1–240 min (default 10)
maxConcurrencyintegernoPhotos processed in parallel, 1–4 (default 2)
maxFileSizeMbintegernoPhotos larger than this become a TOO_LARGE error item (default 25, max 50)
downloadTimeoutSecsintegernoPer-photo download timeout (default 20, max 120)
includeContactSheetbooleannoWrite the CONTACT_SHEET JPEG montage (default true)
webhookUrlstringnoPOST target for the run summary

Output example

A photo item from a hosted fast run (illustrative values):

{
"recordType": "photo",
"photoNumber": 3,
"url": "https://example.com/inspections/oak-ridge/DJI_0003.JPG",
"filename": "DJI_0003.JPG",
"mimeType": "image/jpeg",
"bytes": 6815244,
"width": 5472,
"height": 3648,
"takenAt": "2026-09-14T10:21:07.000Z",
"gps": { "lat": 35.22714, "lon": -80.84312, "altitudeM": 241.3 },
"camera": { "make": "DJI", "model": "FC6310" },
"orientation": 1,
"buildingId": "building-1",
"buildingLabel": "Building 1",
"analysisMethod": "hosted",
"modelTier": "fast",
"model": "claude-haiku-5-5",
"view": "close-up",
"roofType": "3-tab asphalt shingle",
"summary": "South slope near the eave; several missing tabs and a lifted row next to the plumbing vent.",
"findings": [
{
"photoNumber": 3,
"defectType": "missing-shingles",
"severity": "moderate",
"location": "south slope, lower third near eave",
"description": "About four missing tabs with exposed underlayment.",
"quantity": 1,
"unit": "zone",
"confidence": 0.82,
"verificationRequired": true
},
{
"photoNumber": 3,
"defectType": "pipe-boot-or-vent-defect",
"severity": "minor",
"location": "plumbing vent, south slope",
"description": "Cracked rubber collar on the pipe boot.",
"quantity": 1,
"unit": "ea",
"confidence": 0.7,
"verificationRequired": true
}
],
"findingCount": 2,
"confidence": 0.78,
"tokensIn": 2140,
"tokensOut": 310,
"modelCostUsdEstimate": 0.0004,
"sentWidth": 1120,
"sentHeight": 747,
"processingMs": 4210,
"fetchedAt": "2026-10-19T09:12:44.118Z"
}

A building item (estimate computed from the EXAMPLE price list):

{
"recordType": "building",
"id": "building-1",
"label": "Building 1",
"photoNumbers": [1, 2, 3, 4, 5, 6, 7],
"groupedBy": "gps",
"centroid": { "lat": 35.22711, "lon": -80.84309 },
"stories": 2,
"units": null,
"photoRange": "Photos 1–7",
"photoCount": 7,
"analysisMethod": "hosted",
"modelTier": "fast",
"model": "claude-haiku-5-5",
"assessment": {
"roofType": "3-tab asphalt shingle",
"storiesEstimate": 2,
"condition": "fair",
"replacementPriority": 3,
"observations": [
"Missing tabs on the south slope near the eave (Photos 3–4).",
"Cracked pipe boot collar at the plumbing vent (Photo 3).",
"Ridge cap intact; light granule loss on the west slope (Photo 6)."
],
"notes": null,
"confidence": 0.74
},
"findingCount": 4,
"findingsBySeverity": { "minor": 2, "moderate": 2, "severe": 0 },
"findingsByType": { "missing-shingles": 2, "pipe-boot-or-vent-defect": 1, "granule-loss": 1 },
"estimate": {
"scope": [
{ "action": "shingle-zone-repair", "description": "Shingle zone repair — remove and replace missing, torn or creased shingles and hand-seal lifted tabs, underlayment as needed (up to 25 sf per zone)", "quantity": 2, "unit": "zone", "photoNumbers": [3, 4], "verificationRequired": true },
{ "action": "boot-or-vent-replacement", "description": "Pipe boot or vent replacement", "quantity": 1, "unit": "ea", "photoNumbers": [3], "verificationRequired": true }
],
"materials": [
{ "name": "3-tab asphalt shingles", "packSize": "bundle (about 33 sf)", "packs": 2, "unitPriceUsd": 50, "amountUsd": 100, "verificationRequired": true },
{ "name": "Roofing nails", "packSize": "5 lb box", "packs": 1, "unitPriceUsd": 30, "amountUsd": 30, "verificationRequired": true },
{ "name": "Roofing cement / sealant", "packSize": "10 oz tube", "packs": 2, "unitPriceUsd": 15, "amountUsd": 30, "verificationRequired": true },
{ "name": "Pipe boot", "packSize": "each", "packs": 1, "unitPriceUsd": 25, "amountUsd": 25, "verificationRequired": true }
],
"materialsSubtotalUsd": 185,
"labor": { "estimatedHours": 0.8, "bundleHours": 2, "priceUsd": 600, "description": "Repair labor — 2 hours incl. setup, cleanup and haul-off", "verificationRequired": true },
"height": { "stories": 2, "priceUsd": 150, "description": "Ladders, safety and staging (2-story building)", "verificationRequired": true },
"totalUsd": 935,
"priced": true,
"verificationRequired": true
},
"verificationRequired": true,
"tokensIn": 3920,
"tokensOut": 540,
"modelCostUsdEstimate": 0.0007,
"processingMs": 6120,
"fetchedAt": "2026-10-19T09:13:02.551Z"
}

In rules mode photo items carry the EXIF fields and building assignment with view, roofType, summary and confidence set to null and empty findings; building items carry the grouping with assessment: null and an empty estimate. If a model call fails or the hosted model is not configured, the item falls back to the rules output with analysisMethod: "rules-fallback", the reason in analysisWarning, and is charged the rules price.

Error items look like { "recordType": "photo", "photoNumber": 5, "url": "…", "error": "NOT_FOUND", "errorMessage": "HTTP 404 for …" } with codes INVALID_URL, DOWNLOAD_FAILED, NOT_FOUND, TIMEOUT, SOURCE_UNAVAILABLE, TOO_LARGE, UNSUPPORTED_TYPE, UNREADABLE_IMAGE and PROCESSING_FAILED. They are charged at the rules price, because the work to discover the problem was done.

If the output saves you time, a review on the Store page helps other buyers find this Actor; the Store invites you to leave one after you have run it a few times.

Pricing

Pay per event. You only pay for what the Actor produces; set a maximum cost per run in the run options to cap spend.

EventPriceNotes
Photo indexed (rules, no model)$0.002Per photo item in rules mode or on a rules-fallback; error items are charged at this price too
Photo analyzed (your Anthropic key)$0.01Per photo analyzed by Claude in byok mode, any tier; your tokens are billed by Anthropic, not here
Building report (your Anthropic key)$0.05Per building rollup in byok mode; tokens billed by Anthropic to your key
Photo analyzed (hosted, fast tier)$0.02Claude Haiku 5.5 on the Actor's key, tokens included; photo downscaled to at most 1120x840
Building report (hosted, fast tier)$0.10Claude Haiku 5.5, up to 8,000 input tokens of findings per building
Photo analyzed (hosted, balanced tier)$0.08Claude Sonnet 5.5, same caps
Building report (hosted, balanced tier)$0.30Claude Sonnet 5.5, same caps
Actor start$0.00005Apify platform event

Building items are not charged in rules mode: there they are an index without findings.

Worked example. A 167-photo inspection of 18 buildings on hosted fast ≈ 167 × $0.02 + 18 × $0.10 = $5.14, about $5, tokens included. The same job on balanced ≈ $18.76 (167 × $0.08 + 18 × $0.30). Bring your own key: ≈ $2.57 here (167 × $0.01 + 18 × $0.05) plus your tokens on your Anthropic bill. Rules only: 167 photos ≈ $0.33.

Spending limit and model tiers. The model is called before its events are charged, so before every model call the Actor checks that your run's maximum total charge still covers the events that call will produce (the photo events for the batch, or the building report). When it does not, the model is not called: the photos get the rules output instead, charged at the rules price, with an analysisWarning that names the tier, the amount and the limit to set (the run's SUMMARY counts these). When not even a rules item fits, the run stops cleanly with a log line and nothing more is charged. A run with no limit set behaves as before. In practice: set the maximum total charge to at least photos × the photo price plus buildings × the building price for the tier you chose. A limit of $1.00 always covers one batch of photos plus one building report on either hosted tier, even at 8 photos per call on balanced (8 × $0.08 + $0.30 = $0.94).

How the hosted prices are set. Against the worst case, not the average. Every photo is downscaled to fit 1120x840 pixels before the call, which is at most 1,200 visual tokens (one per 28x28-pixel patch); each call also carries about 870 tokens of instructions, JSON schema and photo headers, shared by the photos in the batch (photos of one building are packed into near-equal batches of up to photosPerModelCall), and output is capped at 500 tokens per photo. So the most one photo costs in tokens is, on a 1-photo call: fast 2,090 × $0.10/M + 500 × $0.50/M ≈ $0.00046; balanced 2,090 × $2/M + 500 × $10/M ≈ $0.0092; on the default 4-photo batch about 15% less. A building report is text only, capped at 8,000 input tokens of findings and 1,200 output tokens: ≈ $0.0014 and $0.028. Apify pays developers 80% of the price, so every hosted event clears its worst-case token cost by at least 7× (a margin above 85% at the 1-photo worst case: fast 97%, balanced 85.7%, building reports 88% and 98%). Reasoning tokens count inside the output cap (thinking is off on Haiku 5.5 and limited to between tool calls on Sonnet 5.5). The best tier (Claude Opus 5.5, which cannot turn thinking off) is offered only with your own key, where you pay Anthropic for its tokens. A model failure is never charged at the hosted price: the item falls back to the rules index at $0.002.

Limits and fair use

  • Photos are fetched with plain HTTP from Apify datacenter IPs, up to 25 MB each by default (50 MB maximum), with a 20 s download timeout by default. JPEG, PNG, WebP, GIF and TIFF are supported; HEIC is detected but usually cannot be decoded on the platform (patent-encumbered codec), so convert iPhone photos to JPEG first; anything else becomes an UNSUPPORTED_TYPE or UNREADABLE_IMAGE error item.
  • Each photo is downscaled to at most 1120x840 pixels before it is sent to the model, so fine detail visible only at full resolution may be missed; shoot close-ups of the areas that matter.
  • At most 500 photos per run (maxPhotos, default 200). Split larger inspections into several runs.
  • The Actor runs with 1–2 GB of memory because full-resolution drone photos (20 MP and up) are decoded in memory for EXIF, downscaling and the contact sheet; keep maxConcurrency at 2 on 1 GB. Default run memory is 1024 MB.
  • Time budget. Each photo gets one download deadline (downloadTimeoutSecs, default 20 s) that covers redirects and the retries of a 429 or 5xx response; a header or connection stall is not retried, and a 403 or 404 is never retried. A photo that cannot be downloaded in time becomes a TIMEOUT error item, charged at the rules rate like every error item. After three downloads in a row time out on the same host, that host's remaining photos are not requested: each gets one charged SOURCE_UNAVAILABLE error item. A model call that takes longer than 60 seconds is cancelled without a retry; the photos in that call get the rules index at the rules rate, and the building rollup is written without the model's assessment (and without a charge).
  • Only the URLs you give, your own key-value stores and, in model modes, the Anthropic API are contacted. No proxies, no browser. Your anthropicApiKey is stored encrypted by Apify and is never logged or written to the dataset.
  • The default price list is an EXAMPLE with placeholder prices, not market pricing; replace it with your own before quoting.
  • Sample photos (prefilled for the daily test, 960 px Wikimedia Commons thumbnails, all public domain as works of the U.S. federal government): Photo 1, U.S. Navy photo by Mass Communication Specialist 3rd Class Steven Scott Smith; Photo 2, U.S. Navy photo by Mass Communications Specialist 2nd Class John P. Curtis; Photo 3, NPS Photo (U.S. National Park Service, via NPGallery). All via Wikimedia Commons.
  • AI Document to JSON Extractor (same account): turn supplier quotes and material price sheets (PDF, DOCX) into JSON, then feed the prices into this Actor's priceList.

Use from AI agents (MCP)

Pin this Actor in the Apify MCP server with one link: https://mcp.apify.com?tools=owlabee/drone-roof-inspection-report, or let the agent find it with the search-actors tool. It is pay-per-event with limited permissions, so agents can discover it, inspect the input schema with fetch-actor-details and pay per run through agentic payments. Prompts that map directly onto the input:

  1. "Analyze these 120 drone photos of the Oak Ridge apartments, group them by building and give me a repair scope per roof."
  2. "Index these roof photos by building using GPS and make a contact sheet, no AI analysis."
  3. "Inspect these roof photos with my Anthropic key on the balanced tier and price the repairs with my price list."

The agent receives the same dataset records shown in the output example above.

FAQ

Does this need proxies? No. Photos are downloaded over plain HTTP from the URLs you supply, or read from your own key-value stores; there is no third-party site to scrape. An API key is needed only for byok mode.

How is cost controlled? Cost = photos × the photo price of your mode and tier, plus buildings × the building price in model modes. Use maxPhotos, drop photos that do not show a roof, and set the run's maximum total charge; the Actor checks it before every model call and stops cleanly when it is reached. Every model-mode item records tokensIn, tokensOut and modelCostUsdEstimate, and SUMMARY totals them.

How accurate are the counts? They are estimates from photographs, not measurements. The model counts what it can see in a downscaled photo, so counting is approximate: hidden damage, overlapping photos and shadows can push numbers up or down. Every quantity is marked verificationRequired: true and must be verified on the roof before any material is ordered.

Can I supply my own price list? Yes. Pass priceList with your materials (pack size, packs per unit of repair, price), labor bundles, height charges, hours per zone and zone size. The math is deterministic code: packs are rounded up to whole packs per building, the labor bundle is, by default (laborRounding 'down', as in the reference report), the largest one whose hours do not exceed the estimated hours, or with laborRounding 'up' the smallest one that covers them (never below the smallest bundle, never above the largest, which caps the labor charge), and the height charge follows the story count. Without it the Actor uses an EXAMPLE list whose prices are placeholders.

How are photos grouped into buildings? Your buildings labels come first (photo numbers and ranges like "1-7, 158"). When at least 60% of the remaining photos carry GPS, they are clustered by distance (groupingDistanceMeters, default 25 m) and a photo without GPS joins its neighbor in the sequence; otherwise, when most photos carry a capture time, a new building starts where the time jumps by more than groupingGapMinutes (default 10); with neither, every photo goes into one building. Each building item says how it was formed in groupedBy.

Can an AI agent use this? Yes; see "Use from AI agents (MCP)" above for the pin link and example prompts. Schedules and webhooks work the same way from the Console or the API.

Can I try it for free? Yes. The Apify free plan comes with monthly platform credit, and the quick-start input above costs a few cents per run, so you can test it on your own inputs before paying anything.

How do I find this Actor again? Bookmark it on the Store page (the bookmark icon next to the title); bookmarked Actors are listed in your Console, and the Store page shows new versions as they ship.

Disclaimer

Counts and quantities are taken from photographs and will be verified on the roof before any material is ordered or work is scheduled. The report is preliminary, prepared for estimating and field verification, and makes no engineering, structural, code-compliance or insurance determination. The Actor is not a licensed inspector, and its output is machine-generated and may contain errors. You are responsible for having the right to process the images you supply. In model modes the photos are sent to the Anthropic API solely to produce the analysis; in rules mode nothing leaves Apify. No customer data is stored beyond your own run storages (dataset and key-value store).