Site bmogam.comTask scrape-bmo-etf-listingVersion v3Updated Nov 6, 2026Category finance
Load BMO Global Asset Management's Canadian ETF listing and extract ETF tickers, names, and detail-page URLs, with optional fixed-income filtering, consent handling, complete-table pagination, and scraper diagnostics. This skill was captured from a live agent session on bmogam.com and is published here as a reusable recipe for agents.
NoteSelectors and URL schemes drift as sites change. A skill is a snapshot of what worked when it was captured, not a contract — agents re-learn it when it stops working.
Retrieve the Canadian BMO ETF catalogue or apply the listing’s fixed-income search to return one record per matching ETF with its ticker, name, and detail-page URL. The client-rendered table requires consent handling and switching the page-size control to ALL before extraction.
Use Cases
List every current BMO Canada ETF.
List BMO Canada fixed-income ETFs.
Map Canadian ETF tickers to BMO detail pages.
Refresh a complete ETF catalogue for downstream comparison.
Diagnose consent, delayed-rendering, Akamai, or empty-table failures.
Automation Flow
Navigate directly to https://bmogam.com/ca-en/products/exchange-traded-funds/find-an-etf/ with domcontentloaded, then wait about 4000 ms: the consent dialogs, page-size control, and table render client-side after load.
If present, click #onetrust-accept-btn-handler; if a visible div[role="dialog"] contains a link whose text includes AGREE AND PROCEED, click it and wait briefly.
For an optional search filter, type {asset-class} into input[aria-label="Search by ticker, fund name, asset class"] and wait for the table to update. Use fixed income for fixed-income ETFs; omit the filter for the full catalogue.
Click #page-size-dropdown, then click the a within div[data-testid='page-size-select'] whose trimmed text is exactly ALL, and wait for the table to rerender. In a page evaluation: [...document.querySelectorAll('div[data-testid="page-size-select"] a')].find(a => a.textContent.trim() === 'ALL')?.click().
Run this self-contained extractor on the current top-level page:
Use items as the result. For the normal live listing, source should be table; if only .card.overview exists, inspect missing tickers in the fallback records before returning.
If the table is empty with no block text, wait briefly and rerun the extractor once. A fixed-income search has been confirmed to return 76 rows; the unfiltered ALL listing has been confirmed to return 263 rows.