# OLX Brasil Scraper - New Ads & Price Drop Monitor (`neverempty/olx-brasil-new-ads-monitor`) Actor

For car dealers, resellers, property brokers and deal-alert bots: turn on monitor mode and schedule it → get only new OLX Brasil ads and price drops, with the old price. Cars, motos, imóveis, phones and more by keyword, state, price and seller type. BRL price, city, bairro, photos. JSON, CSV, Excel.

- **URL**: https://apify.com/neverempty/olx-brasil-new-ads-monitor.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** E-commerce, Real estate, Automation
- **Features:** Limited permissions
- **Stats:** 2 total users, 2 monthly users, 93.3% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 ad returneds

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/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

## OLX Brasil Scraper - New Ads & Price Drop Monitor

**Turn on monitor mode and schedule it → get only new ads and price drops.** For car dealers (lojistas), resellers, property brokers (corretores) and deal-alert bots across Brazil: the newest OLX Brasil ads for your search (carros usados, motos, imóveis à venda e para alugar, celulares, móveis, every major OLX category, or any OLX search page you paste), with the price in BRL, the previous price, state, city and bairro, the posting time, private or business seller (particular or profissional), photos, and car and property details where OLX shows them. Each scheduled run returns only what moved since the last run among the newest ads of each search (100 by default). The first run returns them once as your starting point.

No OLX account or API key needed. Start with a category and a state, for example cars in SP. Export as JSON, CSV or Excel, or send the new ads to Slack, email or a sheet with an Apify integration.

### What you get

- **New ads only, on a schedule** (`monitorMode`). Each row says what happened in `changeType`: `new` (posted since the last run), `price_drop` (the price went down; the old price is in `previousPrice`), `price_up` (only if you turn on `includePriceIncreases`), or `removed` (an ad you received is gone from the list on two checks in a row; only for searches whose whole list is read). The first run returns the current ads once as the starting point.
- **Renewed ads are not sold to you as new.** OLX moves renewed (bumped) ads back to the top of the newest-first list: in our run of 28 October 2026 with `{"category": "cars", "state": "SP", "maxResultsPerSearch": 100}`, 81 of the 100 newest ads came back with `bumped: true`. Monitor mode returns an ad as `new` only once, and `bumped` tells you which ads were renewed.
- **Every major OLX category, or any OLX search page you paste, newest first, up to 5,000 ads per search**, and up to 10 searches per run. On 28 October 2026 OLX listed 145,712 car ads in São Paulo state (the `adsInSearch` column of our test runs).
- **Price in BRL** with `currency: "BRL"`, plus the crossed-out old price OLX itself shows on some ads (`oldPriceOnOlx`).
- **Car and property details as columns:** brand, model, year, mileage (km), fuel, gearbox, body type, colour, doors, engine size; property type, area in m², quartos, banheiros, vagas, condomínio and IPTU. Every other detail OLX shows on the ad card is in `attributes`.
- **The filters OLX has:** keyword, category, state, region, price range and private or business seller. Or paste any OLX Brasil search page with your filters already set.
- **Each ad once.** An ad found by two searches of the same run is returned and charged once.

### Output

One row per ad. Main columns:

| Column | Meaning |
|---|---|
| `status` | `ok` for an ad row. Other values are free rows (below) |
| `changeType` | Monitor mode: `new`, `price_drop`, `price_up`, `removed` or `unchanged` (only with `includeUnchanged`). Empty in a normal search |
| `isFirstCheck` | `true` on the first run of a watch, when the current ads are returned as the starting point |
| `id`, `url`, `title` | OLX ad ID, the ad page and its title |
| `price`, `currency` | Asking price and `BRL` |
| `previousPrice`, `priceChange`, `priceChangePercent` | Monitor mode, price change rows: the price at the last check, the difference (negative for a drop) and the percentage |
| `oldPriceOnOlx` | The crossed-out old price OLX shows on the ad, when it shows one |
| `category`, `categoryId` | OLX category, for example `Carros, vans e utilitários` or `Apartamentos` |
| `sellerType` | `private` (particular) or `business` (profissional), as OLX marks the ad |
| `state`, `city`, `neighborhood`, `location` | State (UF), city and bairro, and the place as OLX shows it on the card |
| `listedAt`, `bumped` | When the ad was posted or last renewed (UTC), and whether it was renewed |
| `isFeatured`, `pinnedOnTop` | A highlighted ad the seller paid for, and an ad pinned on top of the list |
| `brand`, `model`, `year`, `mileageKm`, `fuel`, `gearbox`, `vehicleType`, `color`, `doors`, `enginePower` | Cars and motorcycles |
| `propertyType`, `areaM2`, `bedrooms`, `bathrooms`, `parkingSpaces`, `condoFee`, `iptu` | Property |
| `attributes` | Every detail on the ad card by its OLX name (for example `regdate`, `mileage`, `gearbox`, `size`, `rooms`, `condominio`) |
| `imageCount`, `imageUrls` | Number of photos, and links to up to 5 of them |
| `firstSeenAt` | Monitor mode: when this watch first saw the ad |
| `positionInSearch`, `adsInSearch` | Position in the newest-first list, and the total OLX reports for the search |
| `searchKeyword`, `searchLocation`, `searchUrl` | The search the row came from; `searchUrl` opens the same search on OLX |
| `watchName`, `checkedAt` | The watch name you gave, and the time of the check |
| `note` | Free rows only: what happened and what to do |

#### Free rows (never charged)

| `status` | When |
|---|---|
| `no-results` | OLX lists no ad for this search. |
| `no-changes` | Monitor mode: no new ads, price changes or removed ads since the last run. |
| `none-matching` | OLX has ads, but each one was already returned by an earlier search of the same run. |
| `more-not-returned` | The search has more ads than `maxResultsPerSearch`, or more than one search can reach; the row says how many and how to narrow it. Monitor mode: more changes than `maxResultsPerSearch` (a later run returns them), or on the first run, how many ads became the starting point. |
| `more-new-than-readable` | Monitor mode: more ads were posted since the last run than this run read, so some new ones may have been missed. Run the watch more often or raise `maxResultsPerSearch`. |
| `not-found` | OLX could not use the search, for example a region it does not know by that name. |
| `blocked` | OLX refused the request. The run stops and says which searches were not run. |
| `unreadable`, `incomplete` | A page could not be read, even after asking again. Nothing is guessed. In a normal search the newest ads from the pages before it are returned and charged (`incomplete`), and nothing after it. In monitor mode nothing is returned or remembered for that search: the next run checks it again. |
| `budget-reached` | The run reached the maximum total charge you set; the rest was not returned and not charged (in monitor mode the next run returns them). |
| `bad-input` | The input could not be used. Nothing was requested. |

### Input

| Field | What it does |
|---|---|
| `monitorMode` | Return only ads that are new since the last run, price drops and, for searches whose whole list is read, removed ads. |
| `keywords` | Words as you would type them in the OLX search box: `iphone 13`, `hilux`, `apartamento 2 quartos`, `bicicleta aro 29`. Each keyword is its own search. |
| `category` | Cars, motorcycles, vehicle parts, property for sale or rent (apartments, houses, land), phones, electronics, computers, video games, appliances, furniture, home and garden, bicycles, sports, fashion, pets, agro, kids items, music, building materials, or all categories. |
| `state` | The state (estado), for example SP, RJ, MG, PR. Empty = all of Brazil. All search fields empty = cars in SP. |
| `region` | An OLX region inside the state, as written in OLX addresses: `sao-paulo-e-regiao`, `grande-campinas`, `rio-de-janeiro-e-regiao`, `belo-horizonte-e-regiao`. For a city or bairro, open it on OLX and paste the address in `searchUrls`. |
| `minPrice`, `maxPrice` | Price range in BRL, applied the same way as the OLX price filter. |
| `sellerType` | `private` (particular) or `business` (profissional). Empty = all. |
| `searchUrls` | OLX Brasil search pages copied from the browser, for example `https://www.olx.com.br/autos-e-pecas/carros-vans-e-utilitarios/estado-sp`. Each is read newest first with its own filters. |
| `maxResultsPerSearch` | Newest ads to read per search, 1-5000. Empty = 100. In monitor mode, the window checked for new ads and price changes on each run. |
| `includePriceDrops` | Monitor mode: return price drops. Empty = yes. |
| `includePriceIncreases` | Monitor mode: also return price increases. Empty = no. |
| `minPriceChangePercent` | Monitor mode: ignore price changes smaller than this percentage (0-90). |
| `includeRemoved` | Monitor mode: return ads gone from the list on two checks in a row, for searches whose whole list fits in the window. Empty = yes. |
| `includeUnchanged` | Monitor mode: also return ads already received that did not change (each one is charged). Empty = no. |
| `watchName` | Give each schedule its own name so separate schedules keep separate memories. |
| `resetMonitoringState` | Forget what this watch remembered; this run is a first check again. |

Up to 10 searches per run (keywords plus search URLs).

### Examples

New Toyota Hilux ads in São Paulo state, every hour, price drops of 3% or more:

```json
{ "monitorMode": true, "watchName": "hilux-sp", "category": "cars", "state": "SP", "keywords": ["hilux"], "minPriceChangePercent": 3 }
```

Apartments for rent in the Rio de Janeiro region up to R$ 4,000 a month:

```json
{ "category": "property-rent", "state": "RJ", "region": "rio-de-janeiro-e-regiao", "maxPrice": 4000 }
```

The newest 1,000 phone ads in São Paulo state from private sellers:

```json
{ "category": "phones", "state": "SP", "sellerType": "private", "maxResultsPerSearch": 1000 }
```

### Monitor mode, step by step

1. First run: reads the newest `maxResultsPerSearch` ads of each search, returns them once (`changeType: new`, `isFirstCheck: true`) and remembers them as the starting point.
2. Later runs: read the same window again and return only ads posted since the last run (`new`), ads you received whose price went down (`price_drop`, with the previous price), and, for searches whose whole list is read, ads you received that are gone two runs in a row (`removed`). When nothing moved, one free `no-changes` row comes back and only the run start fee is charged.
3. Ads not returned because of `maxResultsPerSearch` or a spending limit come back first in the next run. Nothing is judged from a page that could not be read.

Keep one schedule per input and `watchName`. Two overlapping runs of the same watch can both return the same new ad.

### Pricing

You pay per ad row returned, plus a small start fee once per run. In monitor mode the start fee pays for the check, also when nothing changed. Free rows are never charged, and in monitor mode you are not charged again for ads that did not change: unchanged ads are not returned or charged unless you turn on `includeUnchanged`.

The first run of a watch returns and charges up to `maxResultsPerSearch` ads per search (default 100) as the starting point; set it lower for a cheap first run.

### FAQ

**How do I get only new OLX ads for my search?** Turn on `monitorMode`, give the watch a `watchName` and schedule the run hourly or daily. The first run is your starting point; every later run returns only new ads and price drops.

**How often should I schedule it?** Hourly or daily. A whole big state (for example all cars in SP) gets more new ads in an hour than a 100-ad window holds; run it more often, add a keyword, region or price range, or raise `maxResultsPerSearch`. A free row tells you when new ads may have been missed.

**Is a renewed (bumped) ad reported as new?** No. In monitor mode an ad is returned as `new` only once, and ads that only moved back to the top are not returned again.

**What counts as a price change?** A change of the asking price. A price that disappears from an ad is not reported as a change.

**Does it cover the whole of Brazil?** Yes, all 27 states, or leave the state empty to search the whole country.

### Good to know

- Reads only the search result pages OLX shows anyone without logging in. Ad pages are not opened.
- Seller names, phone numbers and emails are not returned; the seller type (private or business) is.
- `removed` is judged only for searches whose whole list is read, so an ad pushed down by newer ads is never called removed.
- Rows are the ads OLX itself lists for the search, in its order. An OLX region page can mix in ads from nearby areas: on 28 October 2026, 53 of the 200 newest rentals on the `rio-de-janeiro-e-regiao` page were elsewhere in RJ state (for example Petrópolis, Macaé, Volta Redonda). Filter on `city` or `neighborhood` to keep one city.
- Unofficial and not affiliated with OLX.

### Thanks for using this Actor

We build these tools for people who run them every day, and we improve them from what users tell us.

- **Missing a field, or need another filter?** Tell us in the **Issues** tab. If the data is there, we add it.
- **Found a bug or a wrong value?** Post the run ID in the **Issues** tab. Wrong data is the thing we fix first.

If this Actor saved you time, a short review helps other people find it.

# Actor input Schema

## `monitorMode` (type: `boolean`):

Turn on monitor mode and schedule it → get only new ads and price drops. Each run returns only ads that are new since the last run, ads whose price changed (with the previous price) and, on short lists read to the end, ads taken down. The first run returns the current ads as the starting point.

## `keywords` (type: `array`):

Optional. Words as you would type them in the OLX search box, for example iphone 13, hilux, apartamento 2 quartos, bicicleta aro 29. Each keyword is its own search. Empty = every ad of the category and place below.

## `category` (type: `string`):

The OLX category to search. Empty = all categories. With every search field empty the run searches cars in São Paulo (SP) as an example.

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

The state (estado) to search. Empty = all of Brazil.

## `region` (type: `string`):

Optional. An OLX region inside the state, written as in OLX addresses, for example sao-paulo-e-regiao, grande-campinas, rio-de-janeiro-e-regiao, belo-horizonte-e-regiao. Needs the state. For a city or neighbourhood, open it on OLX and paste the address in Search URLs.

## `minPrice` (type: `integer`):

Optional. Lowest price in Brazilian reais (BRL), applied by OLX the same way as its own price filter.

## `maxPrice` (type: `integer`):

Optional. Highest price in Brazilian reais (BRL).

## `sellerType` (type: `string`):

Optional. Only ads from private sellers or only from businesses, the same as the OLX filter. Empty = all.

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

Optional. Paste the address of any OLX Brasil search page with your filters set, for example https://www.olx.com.br/autos-e-pecas/carros-vans-e-utilitarios/estado-sp. Each one is its own search, always newest first.

## `maxResultsPerSearch` (type: `integer`):

How many of the newest ads to read per search (1 to 5000; OLX shows one search up to 5000 ads). Empty = 100. In monitor mode this is the window checked for new ads and price changes on each run.

## `includePriceDrops` (type: `boolean`):

In monitor mode, return ads you already received whose price went down, with the previous price. Empty = yes.

## `includePriceIncreases` (type: `boolean`):

In monitor mode, also return ads you already received whose price went up. Empty = no.

## `minPriceChangePercent` (type: `number`):

Optional. In monitor mode, ignore price changes smaller than this percentage (0 to 90). Empty = every change.

## `includeRemoved` (type: `boolean`):

In monitor mode, return ads you already received that are gone from the list on two checks in a row. Only for searches whose whole list fits in the window, so nothing is called removed just because newer ads pushed it out. Empty = yes.

## `includeUnchanged` (type: `boolean`):

In monitor mode, also return ads already received that did not change (each one is charged). Empty = no.

## `watchName` (type: `string`):

Optional. Give each schedule its own name (letters, digits, dot, dash, underscore) so separate schedules keep separate memories. Empty = default.

## `resetMonitoringState` (type: `boolean`):

Forget what this watch remembered, so this run is a first check again.

## Actor input object example

```json
{
  "category": "cars",
  "state": "SP",
  "maxResultsPerSearch": 100
}
```

# Actor output Schema

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

One row per OLX Brasil ad: ID, link, title, price in BRL, category, state, city, bairro, date posted, seller type (private or business), car details (brand, year, km, fuel, gearbox), property details (area, bedrooms, condomínio, IPTU) and up to 5 photos. Monitor mode marks each row new, price_drop, price_up, removed or unchanged, with the previous price. A search with no ads, no changes, an unknown place or a refused request comes back as a free row that says why.

# 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 = {
    "category": "cars",
    "state": "SP",
    "maxResultsPerSearch": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/olx-brasil-new-ads-monitor").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 = {
    "category": "cars",
    "state": "SP",
    "maxResultsPerSearch": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("neverempty/olx-brasil-new-ads-monitor").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 '{
  "category": "cars",
  "state": "SP",
  "maxResultsPerSearch": 100
}' |
apify call neverempty/olx-brasil-new-ads-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,neverempty/olx-brasil-new-ads-monitor"
        }
    }
}
```

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/AvOKqgKSoujtJY0l6/builds/eAEyccCYhZ5XJWYUQ/openapi.json
