# QuintoAndar Scraper - Brazil Rentals & Sales (`dami_studio/quintoandar-scraper`) Actor

Scrape QuintoAndar property listings across Brazil: rent, condo fee, IPTU, total monthly cost, floor area, bedrooms, bathrooms, parking, neighbourhood, amenities and every photo. Search a city or a neighbourhood, or paste a URL. Turn on details for coordinates. You pay per listing returned.

- **URL**: https://apify.com/dami\_studio/quintoandar-scraper.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** Real estate
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.40 / 1,000 property 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

## QuintoAndar Scraper

Pulls property listings off QuintoAndar — Brazil's largest online rental and sale platform — as
clean JSON rows. Rent, condo fee and IPTU, total monthly cost, floor area, bedrooms, bathrooms,
parking, the neighbourhood and street, amenities, every photo, and the listing URL.

Point it at a city, a neighbourhood, or a QuintoAndar URL you already have open. No API key, no
account, nothing to configure.

***

### What you get

Ask for rentals in São Paulo and you get rows like this:

```json
{
  "listingId": "892801690",
  "url": "https://www.quintoandar.com.br/imovel/892801690",
  "businessContext": "rent",
  "forRent": true,
  "forSale": false,
  "rentPrice": 7900,
  "salePrice": null,
  "totalCost": 9010,
  "condoAndIptu": 805,
  "condoPrice": 650,
  "iptu": 155,
  "currency": "BRL",
  "propertyType": "Apartamento",
  "area": 81,
  "bedrooms": 2,
  "bathrooms": 2,
  "suites": 1,
  "parkingSpots": 2,
  "isFurnished": true,
  "acceptsPets": true,
  "isNearSubway": true,
  "constructionYear": 2013,
  "floorMin": 8,
  "floorMax": 11,
  "street": "Avenida Professor Alceu Maynard Araújo",
  "neighbourhood": "Vila Cruzeiro",
  "region": "Chácara Santo Antonio",
  "city": "São Paulo",
  "state": "SP",
  "postcode": "04726-160",
  "latitude": -23.6350041,
  "longitude": -46.7109047,
  "availability": "immediate",
  "visitsUnavailable": false,
  "lastPublishedAt": "2026-09-19T01:50:56.000Z",
  "description": "Apto no condomínio UPHOME Granja Julieta, 81m2, 2 dorms sendo 1 suíte...",
  "amenities": ["VARANDA", "AR_CONDICIONADO", "CHURRASQUEIRA", "ARMARIOS_EMBUTIDOS_NO_QUARTO"],
  "buildingFacilities": ["PISCINA", "ACADEMIA", "SALAO_DE_FESTAS", "PERTO_DE_METRO_OU_TREM"],
  "specialConditions": ["Exclusivity"],
  "rentalYield": 0.0053,
  "coverImage": "https://www.quintoandar.com.br/img/med/892801690-488.5189...JPG",
  "images": ["https://www.quintoandar.com.br/img/med/892801690-488.5189...JPG"],
  "imageCount": 12,
  "searchLocation": "sao-paulo-sp-brasil",
  "searchFilters": [],
  "position": 1,
  "scrapedAt": "2026-09-20T00:08:41.247Z"
}
```

Prices are in Brazilian reais. `condoAndIptu` is the condo fee and the council tax added together,
the way QuintoAndar shows it on a search card; `condoPrice` and `iptu` are the two halves.

### Input

```json
{
  "location": "São Paulo",
  "businessContext": "rent",
  "maxItems": 200
}
```

| Field | What it does |
|---|---|
| `location` | A city — `São Paulo`, `Rio de Janeiro`, `Belo Horizonte`. A neighbourhood written as `Pinheiros, São Paulo`. Or a slug lifted straight out of a QuintoAndar URL, like `pinheiros-sao-paulo-sp-brasil`. |
| `businessContext` | `rent` or `sale`. |
| `maxItems` | Hard cap on rows, 1–2000. You pay per row returned. |
| `includeDetails` | Off by default. See below. |
| `locations` | More places, one per line. |
| `startUrls` | Paste search pages or single listings. |
| `proxyConfiguration` | Leave it alone unless you need traffic to leave from your own network. |

#### Pasting URLs

Both of these work, and any filters already in a search URL are kept:

```
https://www.quintoandar.com.br/alugar/imovel/sao-paulo-sp-brasil/apartamento/2-quartos
https://www.quintoandar.com.br/imovel/892801690
```

A single listing URL always comes back with every field filled in.

#### `includeDetails` — when you need coordinates

QuintoAndar's search results do not carry map coordinates, and they show the condo fee and the IPTU
added together rather than apart. Turn `includeDetails` on and the actor opens each listing page to
fill in:

`latitude`, `longitude`, `condoPrice`, `iptu`, `postcode`, `suites`, `acceptsPets`, `isNearSubway`,
`constructionYear`, `floorMin`, `floorMax`, `availability`, `lastPublishedAt`, `description`, `state`

It costs one extra request per listing and moves roughly forty times more data, so a 200-row run
goes from about fifteen seconds to several minutes. Leave it off if you are after prices and sizes;
turn it on if you are mapping things or modelling yields. Without it those fields come back `null`
rather than guessed.

### How deep it goes

QuintoAndar does not paginate. Every search URL on the site returns its first two dozen or so
matches and there is no page two — `/pagina-2` exists, answers HTTP 200, and hands back the same
listings. So when you ask for more than that, the actor asks narrower questions instead: it walks
the neighbourhoods QuintoAndar links from your city, then splits by property type, bedroom count and
a few amenities, and de-duplicates as it goes.

That works well. A run measured on 2026-09-19 collected **200 unique São Paulo rentals from 9
requests in 15 seconds**. It is not exhaustive, though, and the honest version is in the limits
section below.

### Pricing

You are charged per listing returned, and only for listings.

Free, every time:

- the sample row you get back when you run it with no input
- diagnostic rows — an unknown location, a URL it cannot read, a city with nothing listed
- runs that find nothing

Duplicates are removed before anything is charged, so if two searches surface the same property you
pay once.

### What this does not do

- **No pagination, so no full-city dump.** Two dozen listings per URL is QuintoAndar's own ceiling,
  not a setting. The neighbourhood walk gets you into the hundreds; it will not get you all 71,000
  São Paulo rentals, and nothing that reads the public site can.
- **No coordinates unless you ask for them.** `latitude`, `longitude`, `condoPrice`, `iptu`,
  `postcode` and the rest of that group are `null` until you switch `includeDetails` on. They are
  not on the search results at all.
- **QuintoAndar is not everywhere.** It covers 99 cities. Several are rent-only — ask for sale
  listings in Salvador and you get told the market is empty, because QuintoAndar's own answer is
  zero. Recife has three rentals in the entire city. You get a diagnostic row saying so, uncharged,
  rather than an empty dataset you have to guess about.
- **`salePrice` on a rental is not an asking price.** QuintoAndar attaches an indicative sale value
  to some properties that are only being let. Check `forSale` before you treat it as one.
- **Amenity and facility codes are QuintoAndar's own**, in Portuguese and upper case —
  `PODE_TER_ANIMAIS_DE_ESTIMACAO`, `PERTO_DE_METRO_OU_TREM`. They are passed through unchanged
  rather than translated, so they stay stable if you key off them.
- **Listings disappear.** A property is pulled the moment it is rented or sold, so a listing URL you
  saved last week may return nothing. That comes back as an uncharged diagnostic row.
- **Ordering is QuintoAndar's relevance ranking** and it shifts between requests. Run the same
  search twice and the set will be close but not identical. Nothing is sorted by price unless you
  sort it yourself.

### FAQ

**Do I need a QuintoAndar account or an API key?**
No. It reads the public site. There is nothing to sign up for and no key to paste.

**Can I get every listing in a city?**
No, and nor can anything else that reads the public site — QuintoAndar caps a search at its first
two dozen results and offers no page two. Asking neighbourhood by neighbourhood gets you into the
hundreds, which is what this actor does automatically.

**How do I scrape one specific property?**
Paste its URL into `startUrls`. A single listing always comes back complete, coordinates included,
whatever `includeDetails` is set to.

**How do I get latitude and longitude?**
Set `includeDetails` to `true`. It costs an extra request per listing.

**Why is `salePrice` filled in on a property that is only for rent?**
QuintoAndar publishes an indicative sale value for some rentals. `forSale` tells you whether it is
actually on the market.

**What happens if I misspell the location?**
You get an uncharged diagnostic row naming the problem. A slug QuintoAndar does not recognise is
particularly worth catching, because the site answers those with listings from somewhere else
entirely — the actor throws those away rather than charge you for the wrong city.

**Does it work for buying as well as renting?**
Yes. Set `businessContext` to `sale`. Be aware that a number of QuintoAndar cities are rent-only.

**How fast is it?**
Measured on 2026-09-19: 12 listings in 2 seconds, 200 listings in 15 seconds. With
`includeDetails` on, budget roughly a second per listing.

**Is the output stable enough to build on?**
Field names and types do not change. Which fields are populated depends on `includeDetails` and on
what the owner filled in — `description` and `constructionYear` are blank on plenty of listings and
come back `null` rather than made up.

# Actor input Schema

## `location` (type: `string`):

A city QuintoAndar covers — "São Paulo", "Rio de Janeiro", "Belo Horizonte", "Curitiba". You can also paste a neighbourhood slug straight from a QuintoAndar URL, like "pinheiros-sao-paulo-sp-brasil", which gives you a much tighter result set.

## `businessContext` (type: `string`):

Which side of QuintoAndar to read. Several cities are rent-only — if you ask for sale listings there the run tells you so instead of returning nothing.

## `maxItems` (type: `integer`):

Hard cap on rows across everything you asked for (1-2000). You are charged per listing returned. QuintoAndar hands out about 26 listings per search URL, so anything above that is collected by searching neighbourhood by neighbourhood — which takes roughly one request per 24 extra listings.

## `includeDetails` (type: `boolean`):

Off by default. Turn it on and the actor opens every listing to fill in latitude and longitude, the condo fee and IPTU split apart, postcode, suites, pets, construction year, availability and the owner's own description. It costs one extra request per listing and makes the run roughly forty times heavier, so leave it off unless you need those fields.

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

Extra cities or neighbourhood slugs, one per line. Runs alongside the field above.

## `startUrls` (type: `array`):

Paste search pages (https://www.quintoandar.com.br/alugar/imovel/sao-paulo-sp-brasil/apartamento/2-quartos) or single listings (https://www.quintoandar.com.br/imovel/892801690). Filters already in the URL are kept. A single listing URL always comes back with the full field set.

## `proxyConfiguration` (type: `object`):

Leave this alone. QuintoAndar answers this actor without a proxy, and the run is faster and cheaper that way. Set it only if you need traffic to leave from a particular network of your own.

## Actor input object example

```json
{
  "location": "São Paulo",
  "businessContext": "rent",
  "maxItems": 50,
  "locations": [],
  "startUrls": [],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

One row per listing: rent, sale price, condo fee and IPTU, total cost, floor area, bedrooms, bathrooms, suites, parking, furnished flag, neighbourhood and city, coordinates and postcode when the full listing page is read, amenities, building facilities, photo URLs and the listing URL. Empty input, an unrecognised URL or a location QuintoAndar does not cover writes an uncharged sample or diagnostic row instead.

# 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 = {
    "location": "São Paulo",
    "businessContext": "rent",
    "maxItems": 50,
    "includeDetails": false,
    "locations": [],
    "startUrls": [],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("dami_studio/quintoandar-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 = {
    "location": "São Paulo",
    "businessContext": "rent",
    "maxItems": 50,
    "includeDetails": False,
    "locations": [],
    "startUrls": [],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("dami_studio/quintoandar-scraper").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 '{
  "location": "São Paulo",
  "businessContext": "rent",
  "maxItems": 50,
  "includeDetails": false,
  "locations": [],
  "startUrls": [],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call dami_studio/quintoandar-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/quintoandar-scraper"
        }
    }
}
```

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/fqqOe4oHZvboD1JFM/builds/oBdn92yJ1TrNoFMLC/openapi.json
