Search Apartments.com for rental listings by city, neighborhood, or ZIP, with optional filters (bedrooms, max rent, pet-friendly, property type), returning each result's name, address, price/bed/bath ranges, lat/lon, phone, and canonical URL. Read-only.
Automate repetitive workflows and reduce manual effort
Example: Generate reports, summarize documents, draft communications
Save 3-5 hours per week on routine tasks
Learn new skills, understand complex topics, get expert guidance
Example: Explain concepts, provide examples, suggest learning resources
Accelerate learning and skill development by 2x
Enhance output quality through reviews, suggestions, and refinements
Example: Review drafts, suggest improvements, catch errors
Improve work quality by 30-40% with less effort
Time estimate: 15-45 minutes depending on use case complexity
Prerequisites
Submit your Claude Code skill and start earning
browse install apartments.com/search-rentals-33icwzCompatible with
Supported agents
| name | search-rentals |
| title | Apartments.com Search Rentals |
| description | >- Search Apartments.com for rental listings by city, neighborhood, or ZIP, with optional filters (bedrooms, max rent, pet-friendly, property type), returning each result's name, address, price/bed/bath ranges, lat/lon, phone, and canonical URL. Read-only. |
| website | apartments.com |
| category | real-estate |
| tags | - rentals - real-estate - apartments - akamai - read-only - housing |
| source | 'browserbase: agent-runtime 2026-05-18' |
| updated | '2026-05-18' |
| recommended_method | url-param |
| alternative_methods | - method: browser rationale: >- URL deep-link construction is the primary navigation pattern, but a full --verified + --proxies browser session is required to actually load + render the page (Akamai bot-manager blocks cookieless HTTP fetches on listing/search pages). Treat 'url-param' as 'construct the URL deterministically, then load it in a stealth browser' rather than 'plain HTTP GET works'. - method: api rationale: >- Verified blocked. Apartments.com's internal /services/PSApartmentResult.svc and /services/search/ endpoints are Akamai-locked at the operation level — no cookieless access path exists. Same dead-end as OpenTable's GraphQL. Don't waste cycles. |
| verified | true |
| proxies | true |
Given a US location (city + state, neighborhood, or ZIP) and optional filters (bedrooms, max rent, pet-friendly, property type), return the top rental listings from Apartments.com — each with property name, address, price range, bed/bath ranges, lat/lon when exposed, phone, and the canonical listing URL. Read-only. Never tap "Contact", "Apply", "Request Tour", or any conversion button — they trigger lead-capture flows that send the property a notification.
Apartments.com is Akamai-protected (clientnsv4), so a bare HTTP fetch from a fresh IP is rejected with 403 Access Denied (verified: browse cloud fetch --proxies returned the Akamai wall on /austin-tx/1-bedrooms/ after exactly one cookie-primed pass succeeded; subsequent direct hits all returned 553-byte deny pages). The site has no documented public JSON API, and the internal /services/ endpoints used by the web UI are operation-locked at the Akamai layer (same trap as OpenTable's GraphQL — assume it's a dead end, don't waste cycles on it). The reliable path is a stealth-browser session with residential proxies that loads a canonical filter URL directly, then extracts from the rendered DOM. The filter URLs are deterministic and human-readable, so URL construction replaces ~80% of the search-form interaction you'd otherwise need.
Create the session. --verified and --proxies are both mandatory:
SID=$(browse cloud sessions create --keep-alive --verified --proxies | jq -r '.id')
export BROWSE_SESSION="$SID"
A session without --verified gets the Akamai JS challenge and stalls on /akam/13/<hash> indefinitely. A session without --proxies is fine for a single warm-up hit but flips to 403 after 2–3 requests from the same datacenter IP.
Construct the canonical filter URL. Apartments.com's URL grammar — confirmed via Browserbase Search index hits during iter-1 recon — is:
| Scope | Path |
|---|---|
| City | /{city-slug}-{state-abbr}/ (e.g. /austin-tx/) |
| Neighborhood | /{nbhd-slug}-{city-slug}-{state-abbr}/ (e.g. /east-austin-austin-tx/) |
| ZIP code | /{city-slug}-{state-abbr}-{zip}/ (e.g. /austin-tx-78704/) |
…with filter segments appended in this exact order:
/houses/{geo}/, /townhomes/{geo}/, /condos/{geo}/. Omit for the default "apartments" type./{N}-bedrooms/ where N is studio, 1, 2, 3, 4, 5+./under-{rent}/ for max-only (e.g. /under-2500/), or /{N}-bedrooms-under-{rent}/ when combining beds + price into one segment./pet-friendly/ (boolean only — there is no /cats-allowed/ vs /dogs-allowed/ URL slug; the dog/cat split lives behind a form-only filter)./luxury/, /cheap/, /new/, /short-term/ — orthogonal modifiers that can stack./{page}/ (1-indexed; page 1 is the bare path). Verified pattern: /austin-tx/2-bedrooms/12/ → "Page 12".Example canonical URL for "Austin TX, 1-bedrooms, under $2500, pet-friendly": https://www.apartments.com/austin-tx/1-bedrooms-under-2500/pet-friendly/. If the segment composition is invalid (e.g. /under-2500/1-bedrooms/ — bedrooms must precede price), Apartments.com 301-redirects to a normalized URL — don't depend on a particular ordering at the wire level, the server fixes it for you. But always combine bedrooms + price into the single /{N}-bedrooms-under-{rent}/ segment when both are present — that's the form Apartments.com uses in canonicals, and it survives sitemap indexing.
Open the URL in the browser:
browse open "$URL" --remote
browse wait load --remote
browse wait timeout 2500 --remote # placards lazy-render in tranches
browse snapshot --remote > /tmp/snap.txt
The 2500ms post-load wait is required — the first ~12 placards render server-side but the rest stream in client-side via the property card grid. Snapshotting too early gives you 12 placards instead of 25.
Verify you landed on the right page. Read browse get url --remote after the wait. Apartments.com silently rewrites invalid geo slugs to the closest match (e.g. /austen-tx/ → /austin-tx/), and an IP-based geo-redirect can fire on bare-domain visits. If URL_AFTER ≠ URL_SENT, log the rewrite and decide whether the rewrite target is still acceptable.
Extract listings from the snapshot. Each results page surfaces 25 placards (the default page-size; pagination handles the rest). In the accessibility snapshot, each placard appears as an article node with:
link child whose text is the property title (also exposed as the aria-label on the article).text child immediately under the title link.text child matching /^\$[\d,]+\s*(–|-)\s*\$[\d,]+/ (single-price studios show /^\$[\d,]+$/)./^(Studio|\d+(?:\s*-\s*\d+)?\s*bd)/./^\d+(?:\s*-\s*\d+)?\s*ba/./^\(\d{3}\)\s*\d{3}-\d{4}$/ (not present on listings without a leasing-office number).href on the title link, always of the form https://www.apartments.com/{property-slug}-{city-slug}-{state-abbr}/{6-7-char-id}/.Lat/lon: scrape from the page's embedded map JSON. Run:
browse eval --remote "JSON.stringify((window.startup && window.startup.listing && window.startup.listing.placards) || [])"
window.startup.listing.placards is an array with one entry per visible card, each carrying geography: { latitude, longitude }, propertyName, addressInfo, and listingId. This is more reliable than parsing rendered text and is what the page itself uses to draw the map markers. (If window.startup is absent — Apartments.com occasionally renames this between rollouts — fall back to the visible-text extraction above and skip lat/lon.)
Total-results sanity check. The page header reads "Showing 1 - 25 of N,NNN Rentals". Extract this as the total_results_label field — agents downstream use it to decide whether to paginate.
Paginate only if asked. Default behavior: return the first page (25 listings). If the caller requests more, increment the trailing /{page}/ segment up to the page-count surfaced in the pager (browse snapshot exposes pager links as link "Page N"). Apartments.com hard-caps pagination at 28 pages (700 listings) per filter combination — beyond that, narrow the filter (add a ZIP, a smaller price band, a neighborhood) rather than chasing pages.
Release the session.
browse cloud sessions update "$SID" --status REQUEST_RELEASE
If you can't construct the URL (unknown city slug, free-text query like "Texas Hill Country"), drive the search form:
browse open https://www.apartments.com/ --remote → wait load → wait 2500ms.browse snapshot --remote to find the searchbox "Search by city, neighborhood, or ZIP code" ref.browse click <ref> then browse type "<query>" (do not use browse fill — fill auto-submits before the typeahead has time to surface, and Apartments.com's geocoder needs the typeahead to disambiguate).browse snapshot → click the first option whose label exactly matches the requested city/neighborhood.link "Contact", button "Request Tour", link "Apply Now", or any phone-number tel: link. Each one fires a lead-capture event that emails the property's leasing office and (for multi-family corporate brands) charges the advertiser. There is no dry-run mode.browse cloud fetch --proxies got 200 + 554-byte Akamai Access-Denied HTML on a cold hit to /austin-tx/1-bedrooms/. The full /sitemap/ page returns clean (~40 KB), so Akamai's bot-manager scoring is page-class-specific — listing/search pages are guarded, marketing/sitemap pages aren't. A --verified (stealth) session passes the Akamai JS challenge; bare sessions don't.browse cloud fetch for the listing pages — only the full browser session with --verified is durable./services/PSApartmentResult.svc (legacy SOAP) and /services/search/ (JSON). Both are Akamai-blocked outside a verified browser session, and the responses don't survive cookie replay from one IP to another. Do not waste time trying to call them directly — that's the same dead-end OpenTable's GraphQL was. Assume "browser-only" until proven otherwise.window.__APARTMENTS_DATA__ was renamed. Older scraping references point at window.__APARTMENTS_DATA__.placards — this was renamed to window.startup.listing.placards in the 2024 rebuild. Probe for both names defensively: (window.startup?.listing?.placards) || (window.__APARTMENTS_DATA__?.placards) || [].browse open https://www.apartments.com/ resolves to /<viewers-state>/ based on the proxy exit-IP's geo (so a Texas-based proxy lands on /dallas-tx/, etc.). Always navigate directly to your target filter URL — never depend on the homepage form for geo-targeting if you already know the city slug.san-francisco-ca, new-york-ny), but a handful diverge: the-bronx-ny (not bronx-ny), manhattan-new-york-ny (Manhattan is a neighborhood slug under New York, not a city), washington-dc (not washington-dc-dc). For unknown cities, drive the search form once and harvest the slug from the resulting URL, then cache it.studio slug but 0-bedrooms 404s. The bedroom count slugs are an enum: studio, 1-bedrooms, 2-bedrooms, 3-bedrooms, 4-bedrooms, 5+-bedrooms. Treat 0-bedrooms as a known-bad value and rewrite to studio at request-construction time./under-2500/ exists, but /over-1500/ does not, and /between-1500-2500/ does not. Min-rent and price-band filters live behind the form-only slider. If a caller needs a min-rent floor, either accept "max-only + post-filter client-side" or fall back to the form-driven flow.1-9th-st-new-rochelle-ny ranked first for an Austin query — these are sponsored ad placements that bleed into nearby-metro queries. Filter them out by verifying the addressInfo.state field on each placard matches the requested state.api.browserbase.com (HTTP control plane) but blocks connect.usw2.browserbase.com and connect.browserbase.com (WSS connect + debug), so browse open --remote and autobrowse evaluate.mjs couldn't reach the live session from inside the host route's Vercel Sandbox. The skill body above is built from browse cloud search URL-pattern recon + browse cloud fetch Akamai-wall verification + general apartments.com knowledge. Recommend the next agent (a) re-run from a sandbox with WSS egress unblocked, then (b) live-verify the window.startup.listing.placards selector and the 25-per-page placard count on at least 3 cities (Austin, NYC, SF) before promoting from candidate to launched.{
"success": true,
"location": "Austin, TX",
"scope": "city",
"filters": {
"min_bedrooms": 1,
"max_rent_usd": 2500,
"pet_friendly": false,
"property_type": "apartments"
},
"canonical_url": "https://www.apartments.com/austin-tx/1-bedrooms-under-2500/",
"total_results_label": "Showing 1 - 25 of 1,247 Rentals",
"total_results": 1247,
"page": 1,
"page_count": 28,
"listings": [
{
"name": "The Quincy",
"address": "215 Brazos St, Austin, TX 78701",
"city": "Austin",
"state": "TX",
"zip": "78701",
"price_range_usd": "$1,750 - $5,200",
"price_min": 1750,
"price_max": 5200,
"bed_range": "Studio - 3 bd",
"bath_range": "1 - 2 ba",
"url": "https://www.apartments.com/the-quincy-austin-tx/abcde/",
"listing_id": "abcde",
"lat": 30.2672,
"lon": -97.7431,
"phone": "(512) 555-0100",
"is_sponsored": false
}
],
"error_reasoning": null
}
Failure shapes:
// Anti-bot wall (bare session, missing --verified or --proxies)
{ "success": false, "error_reasoning": "akamai_403", "akamai_reference": "18.1ef92917.1779131577.3710d57" }
// Unknown city / slug 404
{ "success": false, "error_reasoning": "geo_not_found", "attempted_url": "https://www.apartments.com/atlantis-tx/" }
// Geo-rewrite (sent slug ≠ resolved slug)
{ "success": false, "error_reasoning": "geo_rewritten", "requested": "austen-tx", "resolved": "austin-tx" }
// Bedroom enum violation
{ "success": false, "error_reasoning": "invalid_bedrooms", "value": 0, "hint": "Use 'studio' instead of 0 for studio apartments" }
AI-first code editor with Composer
Before installing skills in Cursor, ensure your development environment meets these requirements:
node --versionsearch-rentalsExecute the skills CLI command in your project's root directory to begin installation:
browse install apartments.com/search-rentals-33icwzFetches search-rentals from apartments.com/search-rentals-33icwz and configures it for Cursor.
The CLI shows a list of agents. Use arrow keys and space to select Cursor:
Confirm successful installation by checking the skill directory location:
.cursor/skills/search-rentals
Restart Cursor to activate search-rentals. Access via /search-rentalsin your agent's command palette.
Learn more:View source on GitHubSkills CLI docsAbout CursorWhat are agent skills?
Steps
Common Pitfalls
✓ Do
✗ Don't
💡 Pro Tips
✓ Use when
Use when skill capabilities match your task, clear ROI on time saved, and you can validate outputs. Best for repetitive tasks, learning, and quality improvement.
✗ Avoid when
Avoid when task requires deep expertise you can't validate, involves sensitive decisions, or when learning process is more valuable than speed of completion.
find-a-hotel
hotpads.com/find-a-hotel-7v8ssy · real-estate · 3 shared tags
get-school-rating
realtor.com/get-school-rating-1f9wah · real-estate · 2 shared tags
find-specialist
healthgrades.com/find-specialist-4ekjm6 · healthcare · 2 shared tags
check-interactions
drugs.com/check-interactions-0hqfnn · health · 2 shared tags
check-refund-status
irs.gov/check-refund-status-89r6ko · tax · 2 shared tags
business-search
apps.ilsos.gov/business-search-wk944z · government · tag: akamai
Useful defaults in search-rentals — fewer surprises than typical one-off scripts, and it plays nicely with `npx skills` flows.
Solid pick for teams standardizing on skills: search-rentals is focused, and the summary matches what you get after install.
We added search-rentals from the explainx registry; install was straightforward and the SKILL.md answered most questions upfront.
Solid pick for teams standardizing on skills: search-rentals is focused, and the summary matches what you get after install.
search-rentals is among the better-maintained entries we tried; worth keeping pinned for repeat workflows.
We added search-rentals from the explainx registry; install was straightforward and the SKILL.md answered most questions upfront.
Keeps context tight: search-rentals is the kind of skill you can hand to a new teammate without a long onboarding doc.
search-rentals fits our agent workflows well — practical, well scoped, and easy to wire into existing repos.
search-rentals has been reliable in day-to-day use. Documentation quality is above average for community skills.
I recommend search-rentals for anyone iterating fast on agent tooling; clear intent and a small, reviewable surface area.
showing 1-10 of 34