Back to Functions

IMPORTHTML

Imports data from a table or list within an HTML page.

WebIMPORTHTML(url, query, index)

IMPORTHTML pulls a table or a list from a web page into your sheet and refreshes it automatically. It is the easiest way to bring public data, such as rankings, price tables, sports results or Wikipedia tables, into a spreadsheet without writing any code.

Syntax

=IMPORTHTML(url, query, index)
  • url: The address of the web page, in quotes (or in a cell), including https://.
  • query: Either "table" or "list": which kind of element to import.
  • index: Which table or list on the page, starting from 1, in the order they appear in the page's HTML.

Basic examples

=IMPORTHTML("https://en.wikipedia.org/wiki/List_of_largest_companies_by_revenue", "table", 1)

Imports the first table on the page. Change 1 to 2 for the second table, and so on.

=IMPORTHTML("https://example.com/page", "list", 1)

Imports the first bulleted or numbered list.

Finding the right index

The index counts every <table> (or list) on the page, including ones that are hidden or look like layout. There is no visual way to see the number, so the practical approach is to try values until the right table appears:

  1. Start with 1.
  2. Increase the number until you find the table you want.
  3. If you get an error for a high number, the page has fewer tables than that.

What the result looks like

The table spills into the cells below and to the right, including the header row. Numbers are converted to numbers where possible, though values with currency symbols, footnotes or text units stay as text. The result needs empty space; if anything blocks the spill area, you get #REF!.

Practical patterns

Pick a few columns

Use QUERY on the imported table, referring to columns as Col1, Col2, and so on:

=QUERY(IMPORTHTML("https://example.com/stats", "table", 1), "select Col1, Col3 where Col3 > 100", 1)

Clean up numbers

Imported numbers often contain symbols, footnote markers or thousand separators. Clean them with REGEXREPLACE and VALUE:

=ARRAYFORMULA(IFERROR(VALUE(REGEXREPLACE(B2:B, "[^0-9.]", ""))))

Get one cell from a table

=INDEX(IMPORTHTML("https://example.com/stats", "table", 1), 3, 2)

Returns the cell in the 3rd row and 2nd column, which is handy for pulling a single number, such as a current rate, into a model.

Build the URL from a cell

=IMPORTHTML("https://example.com/team/" & A2, "table", 1)

Change A2 and the table updates.

Flip the orientation

=TRANSPOSE(IMPORTHTML("https://example.com/stats", "table", 1))

Keep a snapshot

Imported data refreshes and the page may change or disappear. To keep a fixed copy, copy the cells and paste as values only.

Limits and refresh

  • Public pages only. The page must be reachable without logging in. Pages behind a login or paywall return nothing.
  • Static HTML only. IMPORTHTML reads the HTML the server sends. Tables built later by JavaScript (many modern dashboards) are not visible to it. If you see the table in your browser but IMPORTHTML can't find it, this is the likely reason. Look for a page that serves the table as plain HTML, or for an API or CSV link, and use IMPORTDATA or IMPORTXML.
  • Refresh rate. Imported data refreshes periodically (roughly hourly), not instantly. Editing the formula forces a fresh fetch.
  • Request limits. Many IMPORTHTML calls in one spreadsheet can lead to "Loading..." or errors. Import once into a data sheet and refer to it.
  • Blocking. Some sites block automated requests, and IMPORTHTML then returns an error.
  • Terms of use. Check that the site allows this use of its data.

Common errors

  • #N/A: "Imported content is empty". The table index doesn't exist, the page is built with JavaScript, or the site blocked the request.
  • #N/A or error: "Could not fetch URL". The URL is wrong, the site is down or blocking, or the page needs a login.
  • #VALUE!: "Resource at url contents exceeds maximum size". The page is too large. Try a lighter page, or another source.
  • An error about the query argument. query must be exactly "table" or "list", in quotes.
  • #REF!: "Array result was not expanded". Cells in the spill area are not empty.
  • Wrong table. The index points at a different table than you expected. Try neighboring numbers.
  • The layout changed. The site changed its page, shifting the table index. Re-check the index when results go wrong.

IMPORTHTML vs. IMPORTXML vs. IMPORTDATA vs. IMPORTRANGE

  • IMPORTHTML: tables and lists on a web page.
  • IMPORTXML: any element of a web page or XML file, selected with XPath. More flexible, and more technical.
  • IMPORTDATA: a CSV or TSV file from a URL.
  • IMPORTRANGE: a range from another Google Sheet.
  • IMPORTFEED: RSS and Atom feeds.

Frequently asked questions

How do I know which table number to use? Try 1, 2, 3 until the right one appears.

Can it import several tables at once? One call imports one table. Use several formulas.

Can it import pages that need a login? No.

Why is the table missing even though I see it in my browser? It is probably generated by JavaScript.

Related Functions

  • IMPORTXML: Import data from web pages with XPath.
  • IMPORTDATA: Import a CSV file from a URL.
  • IMPORTRANGE: Import a range from another spreadsheet.
  • QUERY: Filter and aggregate imported data.
  • INDEX: Pick a value from the imported table.

Related Articles

Newsletter

More IMPORTHTML examples coming soon.

We are building short, practical updates for Sheets power users.