Purpose
Retrieve the property/listing target URLs and pagination URLs from the APi Real Estate commercial listings page in one navigation and one DOM evaluation.
When to Use
Use for collecting commercial listing detail targets from https://apirealestate.com/commercial-listings, including the links needed to traverse multiple result pages.
Workflow
- Navigate directly to
https://apirealestate.com/commercial-listings. - In the same browser call, run this evaluator after the page loads. It scrolls once to trigger lazy-loaded listing content, then returns the listing targets and pagination links:
(async () => {
window.scrollTo(0, document.body.scrollHeight);
await new Promise((resolve) => setTimeout(resolve, 1500));
const absolute = (a) => {
try {
return new URL(a.href, location.href).href;
} catch {
return null;
}
};
const sameOrigin = (url) => {
try {
return new URL(url).origin === location.origin;
} catch {
return false;
}
};
const unique = (values) => [...new Set(values.filter(Boolean))];
const propertyDetailUrls = unique(
[...document.querySelectorAll('a[aria-label^="Download"]')]
.map(absolute)
.filter((url) => sameOrigin(url)),
);
const paginationLinks = unique(
[
...document.querySelectorAll(
'a[aria-label*="next" i], a[aria-label*="previous" i], a[rel="next"], a[rel="prev"], .pagination a, [data-page-next] a, [data-page-next]',
),
]
.map(absolute)
.filter((url) => sameOrigin(url)),
);
return {
propertyDetailUrls,
paginationLinks,
nextPage:
paginationLinks.find((url) => {
const a = [...document.querySelectorAll("a")].find(
(x) => absolute(x) === url,
);
return (
a && (a.rel === "next" || /next/i.test(a.getAttribute("aria-label") || ""))
);
}) || null,
};
})();- Follow returned pagination URLs directly and repeat the evaluator on each page when the caller needs the complete collection.
Site-Specific Gotchas
- Listing targets are exposed through anchors whose
aria-labelbegins withDownload; preserve theirhrefvalues rather than relying on visible card text. - Listings may be lazy-loaded, so perform the full-page scroll and short wait before extraction.
- Pagination may be represented by
.pagination a,rel="next", an accessible next/previous label, or[data-page-next]; collect all matching links rather than assuming only a next link exists. - Validate whether a returned Download-labelled target is an HTML detail page or a downloadable asset before opening it; the site uses that label for listing-related targets.
Expected Output
An object shaped as:
{ propertyDetailUrls: string[], paginationLinks: string[], nextPage: string|null }.
URLs are absolute, same-origin, and deduplicated.