# Loft Scraper — Brazil Property Data & API (`sian.agency/loft-property-scraper`) Actor

Loft scraper & real estate data API for Brazil. Sale & rent listings: price, condo fee, IPTU, area, bedrooms, suites, parking, address, GPS, neighbourhood, amenities, photos — clean JSON/CSV. Fast overview or full detail. No API key needed.

- **URL**: https://apify.com/sian.agency/loft-property-scraper.md
- **Developed by:** [SIÁN OÜ](https://apify.com/sian.agency) (community)
- **Categories:** Real estate, Automation, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.60 / 1,000 overview listings

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## Loft Scraper — Brazil Property Data & Real Estate API 🏠🇧🇷

[![SIÁN Agency Store](https://img.shields.io/badge/Store-SI%C3%81N%20Agency-1AE392)](https://apify.com/sian.agency?fpr=sian) [![QuintoAndar Scraper](https://img.shields.io/badge/Store-QuintoAndar%20Scraper-1AE392)](https://apify.com/sian.agency/quintoandar-property-scraper?fpr=sian) [![VivaReal Scraper](https://img.shields.io/badge/Store-VivaReal%20Scraper-1AE392)](https://apify.com/sian.agency/vivareal-property-scraper?fpr=sian) [![Zillow Scraper](https://img.shields.io/badge/Store-Zillow%20Scraper-1F4E79)](https://apify.com/sian.agency/zillow-property-scraper?fpr=sian)

#### 🎉 Turn Brazil's Loft listings into clean, analysis-ready datasets — sale & rent, every city, no API key
##### For real-estate analysts, proptech teams, investors, and lead-gen agencies who need structured Brazilian property data fast

---

### 📋 Overview

**Need Loft property data without copy-pasting?** This scraper pulls Loft (loft.com.br) sale and rent listings into a clean, structured dataset — price, condo fee, IPTU, area, bedrooms, suites, parking, address, GPS, neighbourhood, amenities, photos and agency — ready for Excel, your CRM, or a model.

**Why teams choose us:**
- ✅ **Complete records**: ~55 structured fields per listing, including monthly IPTU, condo fee, GPS coordinates and the full photo set
- ⚡ **Two speeds, one tool**: a fast, cheap **Overview** mode for bulk lists and a rich **Detail** mode for full per-listing data
- 🎯 **Search the way you work**: by city, by a pasted search URL, or by specific listing URLs/IDs
- 💰 **Transparent pay-per-result**: you're only charged for listings actually extracted — no charge until your input is validated
- 💎 **Brazil-native**: prices in BRL, Portuguese locale, every state and city covered
- ✨ **No account or API key** needed — paste a city and run

---

### ✨ Features

- 🏙️ **City search**: pull every sale or rent listing in any Brazilian city (e.g. `sao paulo, sp`)
- 🔗 **Search-URL mode**: paste a loft.com.br search URL and the actor mirrors your filters
- 🆔 **Listing-URL mode**: enrich a specific set of listings by URL or ID
- 💵 **Full pricing picture**: sale price, previous price, condo fee, monthly & annual IPTU, monthly expenses, and a computed price per m²
- 📐 **Rich attributes**: area, bedrooms, suites, bathrooms, parking, floor, build year, tower floors, balcony & elevator flags
- 📍 **Geo-ready**: street, neighbourhood, city, state, postal code, latitude & longitude
- 🏢 **Agency & marketplace data**: agency name/ID and marketplace flags for lead generation
- 🏊 **Amenities & media**: condo infrastructure, leisure amenities, unit features, virtual/video tour links and every photo URL
- 📤 **Export anywhere**: JSON, CSV, or Excel straight from the Apify dataset

---

### 🎬 Quick Start

Pick a mode, give it a city (or URLs), and run. Results stream into the dataset as they're extracted — export to JSON/CSV/Excel when it finishes.

```bash
curl -X POST "https://api.apify.com/v2/acts/sian.agency~loft-property-scraper/runs?token=YOUR_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"scrapeMode":"overview","searchMode":"byCity","cities":["sao paulo, sp"],"maxResults":100}'
````

***

### 🚀 Getting Started (3 Simple Steps)

#### Step 1: Choose your mode

**Overview** for fast, cheap lists. **Detail** for the full per-listing record.

#### Step 2: Tell it where to look

Enter one or more cities (`sao paulo, sp`), paste loft.com.br search URLs, or list specific listing URLs/IDs.

#### Step 3: Run and export

Hit **Start** and download your dataset as JSON, CSV, or Excel.

**That's it! In a few minutes, you'll have:**

- A clean table of Brazilian property listings
- Price, costs, attributes, location and contact data
- A reusable dataset you can refresh on a schedule

***

### 📥 Input Configuration

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `scrapeMode` | string | No | `overview` (fast list) or `detail` (full record). Default `overview`. |
| `searchMode` | string | No | `byCity`, `bySearchUrl`, or `byListingUrl`. |
| `cities` | array | No | City facets, e.g. `["sao paulo, sp"]`. |
| `searchUrls` | array | No | loft.com.br search URLs to mirror. |
| `listingUrls` | array | No | Listing URLs or IDs (detail mode). |
| `transactionType` | string | No | `for_sale` or `for_rent`. Default `for_sale`. |
| `orderBy` | string | No | `rankB` (relevance) or `rankA`. Default `rankB`. |
| `neighborhood` | string | No | Optional neighbourhood facet, e.g. `pinheiros, sao paulo, sp`. |
| `minBedrooms` | integer | No | Minimum bedrooms (≥ N). |
| `maxResults` | integer | No | Max listings per run. Default `100`. |
| `proxyCountry` | string | No | `BR` to route via a Brazilian residential exit; blank = direct. |

**Example — overview by city:**

```json
{
  "scrapeMode": "overview",
  "searchMode": "byCity",
  "cities": ["sao paulo, sp"],
  "transactionType": "for_sale",
  "minBedrooms": 2,
  "maxResults": 200
}
```

**Example — detail by listing URL:**

```json
{
  "scrapeMode": "detail",
  "searchMode": "byListingUrl",
  "listingUrls": ["https://loft.com.br/imovel/apartamento-vila-madalena/1fdwpn8"]
}
```

***

### 📤 Output

Results are saved to the Apify dataset with **~55 fields** including:

| Field | Type | Description |
|-------|------|-------------|
| `propertyTitle` | string | Human-readable listing title |
| `url` | string | Canonical listing URL |
| `price` | number | Sale price (BRL) |
| `rental_price` | number | Monthly rent (BRL) |
| `complex_fee` | number | Monthly condo fee (BRL) |
| `property_tax` | number | Monthly IPTU (BRL) |
| `annual_property_tax` | number | Annual IPTU (BRL, detail) |
| `price_per_sqm_brl` | number | Computed price per m² |
| `area` | number | Usable area (m²) |
| `bedrooms` / `suits` / `restrooms` / `parking_spots` | number | Room counts |
| `neighborhood` / `city` / `state` | string | Location |
| `latitude` / `longitude` | number | GPS coordinates |
| `agency_name` | string | Listing agency |
| `photos` | array | All photo URLs |

**Example:**

```json
{
  "listingId": "1fdwpn8",
  "url": "https://loft.com.br/imovel/1fdwpn8",
  "propertyTitle": "Cobertura, Rua Fidalga, Vila Madalena, 2 quartos, 233m2",
  "property_type": "rooftop",
  "transaction_type": "FOR_SALE",
  "price": 2600000,
  "complex_fee": 1800,
  "annual_property_tax": 11262,
  "price_per_sqm_brl": 11158,
  "area": 233,
  "bedrooms": 2,
  "suits": 1,
  "restrooms": 3,
  "parking_spots": 2,
  "neighborhood": "Vila Madalena",
  "city": "São Paulo",
  "state": "SP",
  "latitude": -23.5523645,
  "longitude": -46.6930137,
  "agency_name": "Foxter Imobiliária",
  "currency": "BRL"
}
```

***

### 💼 Use Cases & Examples

#### 1. Market Analysis

**Analysts tracking price and inventory across São Paulo neighbourhoods.**

- **Input:** a city + neighbourhood facet, overview mode
- **Output:** every active listing with price, area and price per m²
- **Use:** build a live comparables table and spot pricing trends

#### 2. Lead Generation

**Agencies building a list of listing agencies and marketplace sellers.**

- **Input:** overview mode across multiple cities
- **Output:** agency names, listing URLs and locations
- **Use:** feed your CRM with fresh, structured prospects

#### 3. Investment Research

**Investors screening yield by comparing rent and sale data.**

- **Input:** for\_sale and for\_rent runs for the same city
- **Output:** price, rent, condo fee and IPTU per property
- **Use:** model gross yield and total carrying cost

#### 4. Price Monitoring

**Proptech teams refreshing a dataset on a schedule.**

- **Input:** a saved search URL, run daily
- **Output:** updated prices and `previous_price` history
- **Use:** detect price drops and new inventory

#### 5. Property Detail Enrichment

**Teams that need deep data on a shortlist.**

- **Input:** detail mode with specific listing URLs/IDs
- **Output:** build year, tower floors, annual IPTU, tour links, full photos
- **Use:** populate a listing page or valuation report

#### 6. Data Feeds & Dashboards

**Builders powering a real-estate dashboard.**

- **Input:** scheduled overview runs by city
- **Output:** clean JSON ready for a database
- **Use:** keep an internal property dashboard current

***

### 🔗 Integration Examples

#### JavaScript/Node.js

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });

const run = await client.actor('sian.agency/loft-property-scraper').call({
  scrapeMode: 'overview',
  searchMode: 'byCity',
  cities: ['sao paulo, sp'],
  maxResults: 100,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0]);
```

#### Python

```python
from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')

run = client.actor('sian.agency/loft-property-scraper').call(
    run_input={
        'scrapeMode': 'overview',
        'searchMode': 'byCity',
        'cities': ['sao paulo, sp'],
        'maxResults': 100,
    }
)

for item in client.dataset(run['defaultDatasetId']).iterate_items():
    print(item)
```

#### cURL

```bash
curl -X POST 'https://api.apify.com/v2/acts/sian.agency~loft-property-scraper/runs?token=YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"scrapeMode":"overview","searchMode":"byCity","cities":["sao paulo, sp"]}'
```

#### Automation Workflows (N8N / Zapier / Make)

1. **Trigger**: Schedule or webhook
2. **HTTP Request**: Call the actor API
3. **Process**: Handle JSON results
4. **Action**: Save to a sheet, notify a channel, or sync to your CRM

***

### 📊 Performance & Pricing

#### FREE Tier (Try It Now)

- **25 listings** per run — full feature access, same quality
- No credit card required
- Perfect for testing and small projects

#### PAID Tier (Production Ready)

- **Unlimited** listings per run
- Faster processing, no caps
- Pay-per-result: only charged for listings actually extracted

💰 **Cost-efficient by design** — Overview mode is the cheap, high-volume path; pay the premium Detail rate only on the listings you choose to enrich.

🔗 [View current pricing](https://apify.com/sian.agency/loft-property-scraper?fpr=sian)

***

### ❓ Frequently Asked Questions

**Q: How many listings can I extract?**
A: FREE tier: 25 per run. PAID tier: unlimited.

**Q: What's the difference between Overview and Detail mode?**
A: Overview is the fast, cheap list — great for bulk. Detail enriches each listing with build year, tower floors, annual IPTU, tour links and the full photo set.

**Q: Can I search a specific neighbourhood?**
A: Yes — set the `neighborhood` facet (e.g. `pinheiros, sao paulo, sp`) or paste a filtered search URL.

**Q: What output formats are available?**
A: JSON, CSV, and Excel — export directly from the Apify dataset.

**Q: Do I need an API key or a Loft account?**
A: No. Just provide a city or URLs and run.

**Q: Which currency are prices in?**
A: Brazilian Real (BRL), as listed on the site.

**Q: Is this legal?**
A: We only extract publicly available listing data. See the legal note below.

***

### 🐛 Troubleshooting

**No results returned**

- Check the city format: `"city, uf"` lowercase (e.g. `sao paulo, sp`)
- Confirm the `transactionType` (for\_sale vs for\_rent) matches what's available

**Fewer results than expected**

- FREE tier is capped at 25 listings — switch to PAID for unlimited
- Raise `maxResults`

**Detail mode is slower**

- Detail fetches each listing individually for the full record — use Overview for bulk lists and Detail only on a shortlist

**Hitting limits at very high volume**

- Set `proxyCountry` to `BR` to spread requests across a Brazilian residential exit

***

### ⚖️ Is it legal to scrape data?

Our actors are ethical and do not extract any private user data, such as email addresses, gender, or location. They only extract what has been chosen to be shared publicly. We therefore believe that our actors, when used for ethical purposes by Apify users, are safe.

However, you should be aware that your results could contain personal data. Personal data is protected by the **GDPR** in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you're unsure whether your reason is legitimate, consult your lawyers.

You can also read Apify's blog post on the [legality of web scraping](https://blog.apify.com/is-web-scraping-legal/).

#### Trademark notice

**Loft** is a trademark of Loft Tecnologia S.A. and/or its respective owners. This actor is an **independent** tool and is **not affiliated with, endorsed by, or sponsored by** Loft. All product names, logos, and brands are property of their respective owners and are used for identification purposes only.

***

### 🤝 Support

[![Telegram Support](https://img.shields.io/badge/Telegram-Support%20Group-0088cc?logo=telegram)](https://t.me/+vyh1sRE08sAxMGRi)

**Join our active support community**

- For issues or questions, open an issue in the actor's repository
- Check the [SIÁN Agency Store](https://apify.com/sian.agency?fpr=sian) for more automation tools
- 📧 <apify@sian-agency.online>

***

**Built by [SIÁN Agency](https://www.sian-agency.online)** | **[More Tools](https://apify.com/sian.agency?fpr=sian)**

# Actor input Schema

## `scrapeMode` (type: `string`):

⚡ **OVERVIEW (default, cheapest):** fast list extraction from Loft's public search API — price, area, rooms, location, photos and more for every listing.

🔎 **DETAIL:** full per-listing record enriched with building metadata (build year, tower floors), annual IPTU, virtual/video tour URLs and the complete photo set. Discovers listings via the overview path, then enriches each one.

## `searchMode` (type: `string`):

How to find listings:

- **📍 By city** — provide one or more city facets (e.g. `sao paulo, sp`).
- **🔗 By search URL** — paste loft.com.br search URLs from your browser.
- **🆔 By listing URL** — provide specific listing URLs or IDs (detail mode only).

## `cities` (type: `array`):

🏙️ **CITY FACETS:** one or more `"city, uf"` strings, e.g. `sao paulo, sp` or `rio de janeiro, rj`.

💡 **TIP:** lowercase, comma + space. Used when **Search mode = By city**.

📋 Click **Bulk edit** to paste several cities (one per line).

## `searchUrls` (type: `array`):

🔗 **SEARCH URLS:** paste loft.com.br search URLs, e.g. `https://loft.com.br/venda/imoveis/sp/sao-paulo`.

💡 Any filters in the URL (bedrooms, neighborhood, …) are carried through. Used when **Search mode = By search URL**.

## `listingUrls` (type: `array`):

🆔 **DETAIL TARGETS:** specific listing URLs (e.g. `https://loft.com.br/imovel/.../1fdwpn8`) or bare IDs (e.g. `1fdwpn8`).

Used when **Scrape mode = Detail** and **Search mode = By listing URL**.

## `transactionType` (type: `string`):

💰 **For sale (venda)** or 🔑 **For rent (aluguel)**. Applies to city / search-URL discovery.

## `orderBy` (type: `string`):

📊 **Sort order** for the search results:

- **rankB** — Loft relevance (default).
- **rankA** — alternate relevance score.

ℹ️ Sorting by price is not supported by Loft's API.

## `neighborhood` (type: `string`):

🏘️ **OPTIONAL NEIGHBORHOOD FILTER:** display facet, e.g. `pinheiros, sao paulo, sp`. Narrows the search to a single neighborhood.

## `minBedrooms` (type: `integer`):

🛏️ **MIN BEDROOMS:** returns listings with at least this many bedrooms (≥ N).

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

🔢 **MAX LISTINGS PER RUN.**

🎯 **TIER-BASED LIMITS:**

- **FREE users:** up to 25 listings per run
- **PAID users:** unlimited

💡 Overview paginates automatically (38 listings per page) until this cap.

## `proxyCountry` (type: `string`):

🌐 **OPTIONAL PROXY:** set to `BR` to route requests through a Brazilian residential exit (helps at very high volume). Leave **blank** to run DIRECT (default, fastest, no proxy cost).

## Actor input object example

```json
{
  "scrapeMode": "overview",
  "searchMode": "byCity",
  "cities": [
    "sao paulo, sp"
  ],
  "transactionType": "for_sale",
  "orderBy": "rankB",
  "maxResults": 100
}
```

# Actor output Schema

## `results` (type: `string`):

Clean structured Loft listings (JSON/CSV/Excel).

# 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("sian.agency/loft-property-scraper").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("sian.agency/loft-property-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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 sian.agency/loft-property-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=sian.agency/loft-property-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Loft Scraper — Brazil Property Data & API",
        "description": "Loft scraper & real estate data API for Brazil. Sale & rent listings: price, condo fee, IPTU, area, bedrooms, suites, parking, address, GPS, neighbourhood, amenities, photos — clean JSON/CSV. Fast overview or full detail. No API key needed.",
        "version": "1.0",
        "x-build-id": "EVpa8tZ5Th4RXFPDW"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/sian.agency~loft-property-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-sian.agency-loft-property-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/sian.agency~loft-property-scraper/runs": {
            "post": {
                "operationId": "runs-sync-sian.agency-loft-property-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/sian.agency~loft-property-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-sian.agency-loft-property-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "scrapeMode": {
                        "title": "🧭 Scrape mode",
                        "enum": [
                            "overview",
                            "detail"
                        ],
                        "type": "string",
                        "description": "⚡ **OVERVIEW (default, cheapest):** fast list extraction from Loft's public search API — price, area, rooms, location, photos and more for every listing.\n\n🔎 **DETAIL:** full per-listing record enriched with building metadata (build year, tower floors), annual IPTU, virtual/video tour URLs and the complete photo set. Discovers listings via the overview path, then enriches each one.",
                        "default": "overview"
                    },
                    "searchMode": {
                        "title": "🔍 Search mode",
                        "enum": [
                            "byCity",
                            "bySearchUrl",
                            "byListingUrl"
                        ],
                        "type": "string",
                        "description": "How to find listings:\n\n- **📍 By city** — provide one or more city facets (e.g. `sao paulo, sp`).\n- **🔗 By search URL** — paste loft.com.br search URLs from your browser.\n- **🆔 By listing URL** — provide specific listing URLs or IDs (detail mode only).",
                        "default": "byCity"
                    },
                    "cities": {
                        "title": "📍 Cities",
                        "type": "array",
                        "description": "🏙️ **CITY FACETS:** one or more `\"city, uf\"` strings, e.g. `sao paulo, sp` or `rio de janeiro, rj`.\n\n💡 **TIP:** lowercase, comma + space. Used when **Search mode = By city**.\n\n📋 Click **Bulk edit** to paste several cities (one per line).",
                        "default": [
                            "sao paulo, sp"
                        ],
                        "items": {
                            "type": "string"
                        }
                    },
                    "searchUrls": {
                        "title": "🔗 Search URLs",
                        "type": "array",
                        "description": "🔗 **SEARCH URLS:** paste loft.com.br search URLs, e.g. `https://loft.com.br/venda/imoveis/sp/sao-paulo`.\n\n💡 Any filters in the URL (bedrooms, neighborhood, …) are carried through. Used when **Search mode = By search URL**.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "listingUrls": {
                        "title": "🆔 Listing URLs or IDs",
                        "type": "array",
                        "description": "🆔 **DETAIL TARGETS:** specific listing URLs (e.g. `https://loft.com.br/imovel/.../1fdwpn8`) or bare IDs (e.g. `1fdwpn8`).\n\nUsed when **Scrape mode = Detail** and **Search mode = By listing URL**.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "transactionType": {
                        "title": "🏷️ Transaction type",
                        "enum": [
                            "for_sale",
                            "for_rent"
                        ],
                        "type": "string",
                        "description": "💰 **For sale (venda)** or 🔑 **For rent (aluguel)**. Applies to city / search-URL discovery.",
                        "default": "for_sale"
                    },
                    "orderBy": {
                        "title": "↕️ Order by",
                        "enum": [
                            "rankB",
                            "rankA"
                        ],
                        "type": "string",
                        "description": "📊 **Sort order** for the search results:\n\n- **rankB** — Loft relevance (default).\n- **rankA** — alternate relevance score.\n\nℹ️ Sorting by price is not supported by Loft's API.",
                        "default": "rankB"
                    },
                    "neighborhood": {
                        "title": "🏘️ Neighborhood facet",
                        "type": "string",
                        "description": "🏘️ **OPTIONAL NEIGHBORHOOD FILTER:** display facet, e.g. `pinheiros, sao paulo, sp`. Narrows the search to a single neighborhood."
                    },
                    "minBedrooms": {
                        "title": "🛏️ Minimum bedrooms",
                        "minimum": 1,
                        "type": "integer",
                        "description": "🛏️ **MIN BEDROOMS:** returns listings with at least this many bedrooms (≥ N)."
                    },
                    "maxResults": {
                        "title": "🔢 Max results",
                        "minimum": 1,
                        "type": "integer",
                        "description": "🔢 **MAX LISTINGS PER RUN.**\n\n🎯 **TIER-BASED LIMITS:**\n- **FREE users:** up to 25 listings per run\n- **PAID users:** unlimited\n\n💡 Overview paginates automatically (38 listings per page) until this cap.",
                        "default": 100
                    },
                    "proxyCountry": {
                        "title": "🌐 Proxy country (optional)",
                        "type": "string",
                        "description": "🌐 **OPTIONAL PROXY:** set to `BR` to route requests through a Brazilian residential exit (helps at very high volume). Leave **blank** to run DIRECT (default, fastest, no proxy cost)."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
