Web.BrowserContents
Accessing DataReturns the HTML of a URL as rendered by a web browser, including JavaScript-generated content.
Syntax
Web.BrowserContents(url as text, optional options as nullable record) as textParameters
| Name | Type | Required | Description |
|---|---|---|---|
url | text | Yes | The URL of the web page to render. |
options | record | No | An optional record with options. Supports WaitFor to control when the browser considers the page fully loaded. |
Return Value
text — The fully rendered HTML source of the web page after JavaScript execution, as a text value.
Remarks
Web.BrowserContents opens the specified URL in an embedded headless Chromium browser, executes JavaScript, waits for the page to render, and returns the resulting HTML source as text. This is fundamentally different from Web.Contents, which sends an HTTP request and returns only the raw server response without running any JavaScript. Use Web.BrowserContents when the data you need is generated client-side — for example, tables populated by a JavaScript framework (React, Angular, Vue), content loaded via AJAX after the initial page load, or data that requires scroll/interaction events to appear.
Availability: Web.BrowserContents is available only in Power BI Desktop. It is not supported in Power BI Service cloud refresh, Excel Desktop, Excel Online, dataflows, or Fabric Notebooks. For scheduled refresh in Power BI Service, the report must use an on-premises data gateway installed on a machine that has Chromium/Edge available (typically a Windows machine with Power BI Desktop or the gateway installed).
Authentication: Only anonymous (unauthenticated) access is supported. The function opens the URL in a browser that has no saved credentials. If the target page requires a login, cookies, or tokens, Web.BrowserContents cannot authenticate. For authenticated web sources, use Web.Contents with appropriate headers or credentials configured in the data source settings.
The WaitFor option: By default, the function waits for the page's initial load event. Use the WaitFor sub-record in the options parameter to customize this:
- [WaitFor = [Timeout = #duration(0, 0, 0, 30)]] — wait up to 30 seconds, then capture whatever HTML has rendered.
- [WaitFor = [Element = "table.results"]] — wait until an element matching the CSS selector table.results appears in the DOM before capturing HTML. This is the most reliable approach for dynamically loaded content.
Typical workflow: ```powerquery ```powerquery ```powerquery ```powerqueryWeb.BrowserContents returns raw HTML text. Pass it to Web.Page to automatically extract all elements, or to
Html.Table for precise CSS-selector-based extraction. Do not call Web.BrowserContents inside a function applied per-row (e.g., inside Table.AddColumn) — it renders a full browser instance each time and is very slow.Examples
Example 1: Fetch the JavaScript-rendered HTML of a page
Web.BrowserContents("https://example.com/dynamic-table")Example 2: Render a page and extract HTML tables using Web.Page
let
Html = Web.BrowserContents("https://example.com/dynamic-table"),
Tables = Web.Page(Html),
FirstTable = Tables{0}[Data]
in
FirstTableExample 3: Wait for a specific DOM element to appear before capturing HTML
let
Html = Web.BrowserContents(
"https://example.com/slow-loading",
[WaitFor = [Element = "table.data-table"]]
),
Data = Html.Table(
Html,
{{"Name", "td.name"}, {"Score", "td.score"}},
[RowSelector = "table.data-table tr.data-row"]
)
in
DataExample 4: Wait with a fixed timeout duration
let
Html = Web.BrowserContents(
"https://example.com/dashboard",
[WaitFor = [Timeout = #duration(0, 0, 0, 30)]]
),
Tables = Web.Page(Html)
in
TablesCompatibility