# Buildium Scraper — US Rentals + Email & Phone from Any PM Site (`memo23/buildium-scraper`) Actor

Turn any Buildium / ManageBuilding rentals URL into live vacancies with office email and phone. Public MITS XML: rent, beds, baths, photos, apply URL, Email, PhoneNumber. One GET per manager. HTTP only, no login. JSON, CSV or Excel. You bring the PM URL — not a weekly dump.

- **URL**: https://apify.com/memo23/buildium-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Real estate, Lead generation
- **Stats:** 17 total users, 16 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 results

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

## Buildium Scraper — US Rentals + Email & Phone from Any PM Site

**Turn any Buildium / ManageBuilding rentals URL into structured vacancies — including office email and phone.** Paste `https://{tenant}.managebuilding.com/Resident/public/rentals`. The actor hits that manager's public MITS XML feed (one GET) and returns rent, beds, baths, photos, apply URL, email, and phone.

### Why Use This Scraper?

- **Public XML, not HTML archaeology.** Buildium documents `XMLRentals.ashx` as the listing feed. We use it.
- **Email and phone in the feed.** HousingFeed's Buildium dump ships listing facts only. The XML includes `<Email>` and `<PhoneNumber>`.
- **One request per manager.** No pagination crawl, no browser.
- **URL-in.** You choose the property manager. Not a weekly national snapshot.
- **Apply URL included.** `{origin}/Resident/rental-application/new/apply?listingId=…`

### Overview

One dataset row per advertised floorplan/listing in that tenant's public feed. Typical use: you already have ManageBuilding URLs (from a PM directory, a website, or a client) and want inventory + contacts. There is no "all Buildium in Texas" search — you need origins.

### Supported Inputs

| Input | What it is | Example |
|---|---|---|
| Public rentals page | HTML list | `https://zoulproperties.managebuilding.com/Resident/public/rentals` |
| XML feed | Direct MITS URL | `https://zoulproperties.managebuilding.com/Resident/PublicPages/XMLRentals.ashx` |
| `startUrl` | Single-URL convenience field | same as one `startUrls` item |

The actor rewrites any origin to `/Resident/PublicPages/XMLRentals.ashx` (Buildium 301s that to `/resident/api/public/listingFeeds`).

**Unsupported:** authenticated `api.buildium.com` (needs client id/secret), tenant login portals, and city-wide search with no URL.

**Seed list:** this repo ships `seeds/start-urls.json` — **~526** `{tenant}.managebuilding.com/Resident/public/rentals` URLs mined from Common Crawl and live-checked against the public XML feed.

### Use Cases

| Audience | What they get |
|---|---|
| **Rental lead-gen** | Office email + phone for managers you already have URLs for |
| **PropTech / aggregators** | Inventory that never syndicated to Zillow |
| **Researchers** | Asking rents and unit mix for a named manager |
| **Agencies** | A dump of one competitor's public vacancies |

### How It Works

![How the Buildium scraper works](https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/how-it-works-buildium.png)

1. Paste one or more ManageBuilding rentals (or XML) URLs.
2. The actor fetches that origin's public MITS XML feed.
3. Each `<Floorplan>` becomes a dataset row (rent, beds, photos, contacts).
4. It stops at `maxItems`.

### Input Configuration

| Field | Type | Default | What it does |
|---|---|---|---|
| `startUrls` | string list | sample NE manager | Rentals page or XML URL |
| `startUrl` | string | empty | Same, for a single URL |
| `maxItems` | integer | 100 | Cap on saved listings (free accounts hard-capped at 100) |
| `includeInactive` | boolean | false | `?listings=all` — active + inactive |
| `proxy` | proxy object | off | Optional |

**Example — one manager, 25 listings**

```json
{
  "startUrls": ["https://zoulproperties.managebuilding.com/Resident/public/rentals"],
  "maxItems": 25
}
```

**Example — two managers, include inactive**

```json
{
  "startUrls": [
    "https://zoulproperties.managebuilding.com/Resident/public/rentals",
    "https://wisechoiceproperties.managebuilding.com/Resident/public/rentals"
  ],
  "includeInactive": true,
  "maxItems": 200
}
```

### Output Overview

Each row is one public listing. Email/phone come from the property's XML `<Address><Email>` and `<Phone><PhoneNumber>` (and management-level contacts when present).

### Output Samples

URL `https://zoulproperties.managebuilding.com/Resident/public/rentals`:

```json
{
  "platform": "buildium",
  "id": "buildium:zoulproperties:115843",
  "listingId": "115843",
  "tenant": "zoulproperties",
  "url": "https://zoulproperties.managebuilding.com/Resident/public/rentals/115843",
  "title": "Royal Prince - 7A",
  "address": "311 North Lincoln Avenue - 7A, Grand Island, NE, 68801",
  "city": "Grand Island",
  "state": "NE",
  "zip": "68801",
  "rent": 950,
  "beds": 1,
  "baths": 1,
  "sqft": 550,
  "email": "inquiries@grandislandrealty.net",
  "phone": "308-382-4247",
  "officeName": "Grand Island Realty",
  "applyUrl": "https://zoulproperties.managebuilding.com/Resident/rental-application/new/apply?listingId=115843"
}
```

### Key Output Fields

| Group | Fields |
|---|---|
| Identity | `platform`, `id`, `listingId`, `propertyId`, `tenant`, `url` |
| Listing | `title`, `description`, `rent`, `rentMin`, `rentMax`, `deposit`, `beds`, `baths`, `sqft`, `propertyType`, `unitCount` |
| Location | `address`, `street`, `city`, `state`, `zip` |
| Media | `image`, `images[]`, `amenities[]` |
| Contact | `officeName`, `email`, `emails[]`, `phone`, `phones[]`, `applyUrl` |
| Meta | `currency`, `scrapedAt` |

`latitude` / `longitude` are reserved and currently null — the MITS feed we probed did not include coordinates.

### FAQ

**Can I scrape all Buildium listings in a state without URLs?** Not from Buildium itself. Use `seeds/start-urls.json` (~526 live-checked ManageBuilding origins) or `housingfeed/buildium-scraper` if you want a pre-built geo DB instead of live URL-in.

**Is the XML allowed?** Buildium publishes it for websites to embed listings (`help.buildium.com` → "Rental listings in XML"). We only read that public feed.

**Why might email be empty?** Some managers leave `<Email />` blank in the feed. Phone can still be present.

**Do I need API keys?** No. `api.buildium.com` is a different, authenticated product.

### Support

Open an issue on the [actor page](https://apify.com/memo23/buildium-scraper/issues/open).

### Additional Services

Need a geo-filtered cut of the seed list, a combined AppFolio+Buildium run, or a private feed? Use the issues tab or [memo23's profile](https://apify.com/memo23). Raw seeds: `seeds/` in this repo.

### Explore More Scrapers

- [AppFolio Scraper](https://apify.com/memo23/appfolio-scraper) — URL-in AppFolio listings + office phone
- [Apartments.com Scraper](https://apify.com/memo23/apartments-cheerio-ppe)
- [Zumper Scraper](https://apify.com/memo23/zumper-cheerio)
- [Zillow Scraper](https://apify.com/memo23/zillow-scraper-ppe)
- More at [apify.com/memo23](https://apify.com/memo23)

### 🤖 For AI Agents & LLM Apps

Compact reference for agents calling this actor via the [Apify MCP server](https://mcp.apify.com) or the Apify API (`memo23/buildium-scraper`).

**Purpose:** Live-scrape rental vacancies from a Buildium/ManageBuilding public rentals URL via the MITS XML feed, including office email and phone.

**Minimal input:**

```json
{
  "startUrls": ["https://zoulproperties.managebuilding.com/Resident/public/rentals"],
  "maxItems": 25
}
```

**Output fields:** `platform`, `id`, `listingId`, `propertyId`, `tenant`, `url`, `title`, `description`, `address`, `street`, `city`, `state`, `zip`, `latitude`, `longitude`, `rent`, `rentMin`, `rentMax`, `currency`, `deposit`, `beds`, `baths`, `sqft`, `propertyType`, `unitCount`, `amenities`, `image`, `images`, `officeName`, `email`, `emails`, `phone`, `phones`, `applyUrl`, `scrapedAt`.

**Behaviors an agent should know:**

- Always set `maxItems`. Default 100; free accounts capped at 100.
- Requires a `*.managebuilding.com` rentals or XML URL. No city-wide search.
- `includeInactive: true` fetches `?listings=all`.
- Coordinates are currently null.
- Proxy off by default.

### ⚠️ Disclaimer

This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by Buildium, RealPage, Inc., or any of their subsidiaries. All trademarks mentioned are the property of their respective owners.

The scraper accesses only the publicly documented rental-listing XML feed and public rentals pages on `*.managebuilding.com` — no authenticated Buildium Open API, tenant records, or content behind a login. Users are responsible for ensuring their use complies with Buildium's Terms of Service, applicable data-protection law (GDPR, CCPA, etc.), and any contractual obligations of their own organization.

### SEO Keywords

buildium scraper, managebuilding scraper, buildium listings api, scrape buildium, buildium rental listings, XMLRentals.ashx, MITS rental feed, property manager listings scraper, US rental scraper, buildium email, buildium phone, off-market rentals scraper, property management inventory, buildium data extraction, RealPage listings

# Actor input Schema

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

One or more public rentals pages or XML feed URLs. Example: https://zoulproperties.managebuilding.com/Resident/public/rentals. The actor converts each origin to /Resident/PublicPages/XMLRentals.ashx. Default: a sample Nebraska manager.

## `startUrl` (type: `string`):

Convenience alternative to startUrls when you have one URL. Merged with startUrls and de-duplicated. Example: https://zoulproperties.managebuilding.com/Resident/public/rentals. Default: empty.

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

Hard cap on listings saved across all start URLs. Free Apify accounts are capped at 100. Example: 5 for a smoke test. Default: 100.

## `includeInactive` (type: `boolean`):

When true, fetches XMLRentals.ashx?listings=all (active + inactive). Default false = currently advertised vacancies only.

## `proxy` (type: `object`):

Optional. Buildium public XML feeds usually load without a proxy. Default: off.

## Actor input object example

```json
{
  "startUrls": [
    "https://zoulproperties.managebuilding.com/Resident/public/rentals",
    "https://bellarentals.managebuilding.com/Resident/public/rentals",
    "https://bodewell.managebuilding.com/Resident/public/rentals"
  ],
  "maxItems": 100,
  "includeInactive": false,
  "proxy": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

# 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 = {
    "startUrls": [
        "https://zoulproperties.managebuilding.com/Resident/public/rentals",
        "https://bellarentals.managebuilding.com/Resident/public/rentals",
        "https://bodewell.managebuilding.com/Resident/public/rentals"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/buildium-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 = { "startUrls": [
        "https://zoulproperties.managebuilding.com/Resident/public/rentals",
        "https://bellarentals.managebuilding.com/Resident/public/rentals",
        "https://bodewell.managebuilding.com/Resident/public/rentals",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("memo23/buildium-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 '{
  "startUrls": [
    "https://zoulproperties.managebuilding.com/Resident/public/rentals",
    "https://bellarentals.managebuilding.com/Resident/public/rentals",
    "https://bodewell.managebuilding.com/Resident/public/rentals"
  ]
}' |
apify call memo23/buildium-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,memo23/buildium-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/twCCfesyjm15VuHnh/builds/KTOozO0sAP74fT9ma/openapi.json
