Provide a fast, reusable scraper for Infrastructure Capital Advisors ETF pages. The site exposes individual funds at direct ticker-based paths and uses table.table-small for compact fund data tables, including fee metadata such as Management Fee.
Use Cases
Use when the caller supplies an ICA fund ticker or ticker-like page slug and needs the fund heading, page metadata, links, tabular holdings, performance, factsheet data, or the exact text/value of a named table row.
Automation Flow
- Build the fund URL directly as
https://infracapfund.com/{ticker}. Preserve the supplied ticker spelling; observed routes include/icap,/scap,/qvol, and/BNDS. - Navigate to that URL with
waitUntil: "domcontentloaded". - If the target table is not populated immediately, wait for
table.table-small tdfor up to 6 seconds. - Run this evaluator on the loaded page. It returns normalized tables, raw HTML for compact tables, and exact matching rows for a requested label such as
Management Fee.
((label = "Management Fee") => {
const clean = (value) => (value || "").replace(/\s+/g, " ").trim();
const wanted = clean(label).toLowerCase();
const tables = [...document.querySelectorAll("table")]
.map((table) => ({
selector: table.matches("table.table-small") ? "table.table-small" : "table",
caption: clean(table.querySelector("caption")?.innerText),
html: table.matches("table.table-small") ? table.outerHTML : undefined,
rows: [...table.querySelectorAll("tr")]
.map((row) => {
const cells = [...row.querySelectorAll("th, td")].map((cell) =>
clean(cell.innerText),
);
return cells.length ? cells : [clean(row.innerText)];
})
.filter((row) => row.some(Boolean)),
}))
.filter((table) => table.rows.length);
const matchingRows = tables.flatMap((table) =>
table.rows
.filter((row) =>
row.some(
(cell) =>
cell.toLowerCase() === wanted || cell.toLowerCase().includes(wanted),
),
)
.map((row) => ({ label, row })),
);
return {
url: location.href,
title: clean(document.title),
h1: clean(document.querySelector("h1")?.innerText),
headings: [...document.querySelectorAll("h2, h3")]
.map((node) => clean(node.innerText))
.filter(Boolean),
managementFeeRows: matchingRows,
tables,
links: [...document.querySelectorAll("a[href]")]
.map((a) => ({ text: clean(a.innerText), href: a.href }))
.filter((link) => link.text || link.href),
};
})();Use managementFeeRows to determine whether the requested row exists and report its exact normalized cell values. Use tables[*].html when the caller specifically requests the raw HTML representation.
Possible Friction Points
- The canonical direct fund host is
infracapfund.com; related navigation also exposesicapfunds.comandwww.infracapfunds.com, including a/fundscatalog, but visiting the catalog is unnecessary when the ticker is known. - Fund pages use ticker-based paths rather than opaque IDs. Do not invent a different slug or use the issuer homepage as an intermediate step.
- Ticker paths may use mixed case, as shown by
/BNDS; retain the caller's path casing when possible. - Compact fund information is commonly rendered in
table.table-small; table contents may appear shortly afterdomcontentloaded, so conditionally wait fortable.table-small tdbefore extraction. - Fee labels may be rendered as table cells with the value in an adjacent cell; match the label cell and preserve the complete row rather than assuming a fixed column count.
- The extractor intentionally includes all tables and page links because different fund pages can expose different table categories and document links.