Purpose
Extract property detail links and visible addresses from Colorado Property search results. The site exposes listing searches through parameterized /listing/list URLs, and listing cards use the .property-card-wrapper selector. The result also includes the first qualifying detail URL for callers that only need the first property.
When to Use
Use when the caller needs listing links, addresses, or the first property's detail-page URL from a Colorado Property search. Replace location, property-type, status, price, sort, and pagination values with the caller's criteria.
Workflow
Navigate directly to the listing collection. Prefer the compact path-style form when all filters are known:
https://www.coloproperty.com/listing/list/typeIds/{type-ids}/exclStatus/{excluded-statuses}/cities/{url-encoded-city}/orderBy/{sort}/prMax/{max-price}The query-style form is also supported and is useful for arbitrary location and page-size settings:
https://www.coloproperty.com/listing/list?searchFor=listing&rawLoc={url-encoded-location}&typeIds={type-ids}&priceMax={max-price}&orderBy={sort}&reportFormat=quick&perPage={page-size}In the same browser call after the page is loaded, run this extractor. It returns every distinct qualifying listing URL paired with the best available visible address, plus the first detail URL for backwards compatibility:
(() => {
const absolute = href => {
try { return new URL(href, location.href).href; } catch (_) { return null; }
};
const isDetail = href => {
const u = absolute(href);
return !!u && u.origin === location.origin &&
/^\\/listing\\/\\d+(?:\\/|$)/.test(new URL(u).pathname);
};
const addressFromCard = card => {
const selectors = [
'[class*="address"]', '[id*="address"]',
'.property-card-address', '.listing-address',
'[data-testid*="address"]'
];
for (const selector of selectors) {
const el = card.querySelector(selector);
const text = el && el.innerText.trim().replace(/\\s+/g, ' ');
if (text) return text;
}
const lines = card.innerText.split(/\\n+/).map(s => s.trim()).filter(Boolean);
const street = lines.find(line =>
/\\b\\d{1,6}\\s+[^\\n,]+\\b(?:street|st|avenue|ave|road|rd|drive|dr|lane|ln|court|ct|circle|cir|place|pl|boulevard|blvd|way|parkway|pkwy|highway|hwy)\\b/i.test(line)
);
return street || null;
};
const cards = [...document.querySelectorAll('.property-card-wrapper')];
const seen = new Set();
const listings = [];
for (const card of cards) {
const href = [...card.querySelectorAll('a[href]')]
.map(a => absolute(a.getAttribute('href')))
.find(isDetail);
if (!href || seen.has(href)) continue;
seen.add(href);
listings.push({ url: href, address: addressFromCard(card) });
}
return {
url: location.href,
count: listings.length,
listings,
firstDetailUrl: listings[0]?.url || null,
firstCardText: cards[0]?.innerText.trim() || null,
reason: listings.length ? null : 'no qualifying property cards found'
};
})()Site-Specific Gotchas
- Listing searches support both path-style filters such as
typeIds,exclStatus,cities,orderBy, andprMax, and query parameters such asrawLoc,priceMax,reportFormat, andperPage. - URL-encode city and location values. Multiple type or status values are comma-separated; encode commas when constructing a URL if required by the client.
- Observed useful modifiers include
typeIds=1,2ortypeIds=1,2,10, ascending price sorting withorderBy=prAsc,reportFormat=quick, andperPage=50. These are optional and must not be imposed when the caller requests different criteria. - Do not guess a property ID or detail-path suffix. Read the actual qualifying
/listing/{numeric-id}anchor from each.property-card-wrapper. - Address markup may vary between result layouts. The extractor first checks address-specific classes or test IDs and then uses a street-address pattern; a missing match is returned as
nullrather than fabricated. - A synthetic click may fail to reveal navigation reliably. Reading descendant anchors is faster and deterministic.
Expected Output
Return an object containing the loaded URL, count, and listings, where each listing has an absolute detail url and an address string or null. Also return firstDetailUrl for callers needing only the first property, firstCardText for verification, and a reason when no qualifying listing cards are present.