IMPORTXML not working? How to fix it, and an alternative when you can't
Updated
IMPORTXML reads the raw HTML Google's servers download, without JavaScript or your login. Find your value in View page source, in an incognito window. In normal tags: fix the XPath. In a script: extract it with REGEXEXTRACT. Missing: no built-in formula reaches it. BrowseWiz reads the page in your Chrome, after login and scripts, and fills a new Google Sheet.
Add to Chrome – it's freeFind the cause in 30 seconds
Open the page in an incognito window, so you see it signed out. Press Ctrl+U (Option+Cmd+U on a Mac) for View page source, not Inspect, and search for your value. Page source is what the server sends, which is what IMPORTXML sees Source 1. Inspect shows the page after scripts ran.
- In the source, inside normal tags: the formula can reach it. Fix the XPath.
- Only inside a script tag, often as JSON:
IMPORTXMLcan return the whole script, andREGEXEXTRACTcan cut your value out of it Source 2, Source 3. It breaks when the site changes its JSON, and one cell holds at most 50,000 characters Source 4, so a long script may not fit. Apps Script can parse the JSON properly, if you write code. - Not there at all: a script loads it later, or only signed-in visitors get it. No built-in formula will find it in the page. On a public page, open DevTools, go to Network > Fetch/XHR and reload. If a request returns your value as JSON, Apps Script can fetch that URL directly Source 4.
See the three cases on practice pages
Quotes to Scrape, a site made for scraping practice, serves the same ten quotes three ways, and the three pages look the same in your browser. Put each URL in A1 and try =IMPORTXML(.
- Normal tags. With
https://in A1, the formula returns the ten quotes.quotes.toscrape.com/ - Inside a script. With
https://, it returns #N/A. Page source shows why: the quotes sit as JSON in aquotes.toscrape.com/ js/ <script>, invar data = [...], and a script draws them.=REGEXEXTRACT(returns the first quote. The JSON writes the curly quote marks asIMPORTXML( A1, "// script[contains( ., 'var data')]"), "\\u201c( .+? )\\u201d") \u201cand\u201d. In the pattern,\\matches one backslash, so it finds those codes and leaves them out. If the site changes its JSON, the formula breaks. - Not there at all. With
https://, it returns #N/A, and page source has only an emptyquotes.toscrape.com/ scroll <div class="quotes">. Open DevTools, go to Network > Fetch/XHR and reload: a request to/returns the quotes as JSON. Apps Script can fetch that URL withapi/ quotes? page=1 UrlFetchApp.fetchand read it withJSON.parseSource 5.
Why IMPORTXML and IMPORTHTML fail
Each cause below ends with whether a change to the formula can fix it.
- The page uses JavaScript. Import functions read the HTML the server sends and don't run scripts Source 4. The cell shows #N/A and says the imported content is empty Source 1. Google's help doesn't mention this. Fixable only when the data sits in a script on the page, as above.
- The page needs a login. The request comes from Google's servers, without your browser session Source 4, so it sees what a signed-out visitor sees, usually a sign-in page. No formula fix.
- The XPath doesn't match the raw HTML. This gives the same empty result Source 6, which is why the page source test comes first. XPaths copied from DevTools describe the page after the browser changed it Source 1. Browsers add a
<tbody>to tables that lack one Source 7, so a copied/path can match nothing. Fixable.tbody/ - Could not fetch url. The URL must include the protocol, such as
https://Source 8. If it does, the site is probably refusing Google's requests, as some sites do when Sheets sends too many Source 9. No formula gets past a block. - Result too large, or Resource at url contents exceeded maximum size. For the first, Google's fix is an XPath that returns less Source 10. The second means the page itself is over a size limit Google doesn't publish Source 4. Look for a lighter URL with the same data, such as a JSON request from the Network tab, which Apps Script can fetch. Fixable sometimes.
- Stuck on Loading: too many imports. When import functions create too much traffic, cells show "Loading data may take a while because of the large number of requests" Source 10. The quota is the creator's, shared across all the open spreadsheets they created, and Google's fix is to use fewer import functions Source 10. Guides often quote a 50-formula cap; Google's help gives no number. Fixable.
- Stale numbers: the refresh is hourly. Imports check for updates every hour while the document is open. Re-entering the formula forces a refresh; reopening the file doesn't, and
NOW(or) RAND(can't speed it up, because import functions can't reference them Source 10. Partly fixable.)
How to fix the formula
When the value is in the page source, outside any script, try these in order.
- Test the fetch. With
https://in A1,quotes.toscrape.com/ =IMPORTXML(returns Quotes to Scrape. IfA1, "// title") //fails on your page, the fetch is the problem, not your XPath.title - Skip levels.
//works with or without atable[@id='prices']// tr/ td[2] <tbody>. Anchor on an id or class, not a long position path. - Match one class among several.
//matchesspan[contains( @class, 'price')] class="price sale", but alsoprice-oldandunit-price. For the exact class, use//. Use single quotes inside the XPath, because the formula wraps it in double quotes.span[contains( concat( ' ', normalize-space( @class), ' '), ' price ')] - Return one value.
=INDEX(keeps only the first quote from the practice page.IMPORTXML( A1, "// span[@class='text']"), 1) - IMPORTHTML counts from 1.
=IMPORTHTML(is the second table on the page. Tables and lists are numbered separately Source 11.A1, "table", 2)
When to stop fixing the formula
If the formula works, keep it. It's free, it lives in the cell, it needs no extension, and it runs on Google's servers, so it doesn't depend on Chrome being open.
If the value isn't in the page source at all, or you sign in to see the data, no built-in formula can reach it. Switch then, or when the site blocks Google, or when you need fresh rows at a set time, not only while someone has the sheet open. For marketplace product pages on Amazon, Walmart and similar sites, one option is Amapulse, formerly ImportFromWeb: a Sheets add-on that pulls data even from JavaScript-rendered pages, with a one-month free trial that includes 200 credits Source 12.
One thing changes when you switch to BrowseWiz. It can't write into the sheet that holds your IMPORTXML formulas, or into any sheet it didn't create. It creates a new sheet in your Google Drive and keeps writing to it, on every plan. To see those rows next to your formulas, pull them in with IMPORTRANGE and click Allow access the first time Source 13.
IMPORTXML vs IMPORTHTML vs Apps Script vs BrowseWiz
Apps Script here means a script that fetches pages with UrlFetchApp. Google facts come from Google's documentation, and from Stack Overflow where Google's help is silent. Apps Script limits are for a personal Google account.
| Feature | BrowseWiz | IMPORTXML | IMPORTHTML | Apps Script |
|---|---|---|---|---|
| What you write Source 8, Source 11 | A sentence | A formula and an XPath | A formula and a table or list number | JavaScript code |
| Where it runs Source 5 | Your Chrome, in the BrowseWiz Tabs group | Google's servers | Google's servers | Google's servers |
| Pages built with JavaScript Source 3, Source 4 | Yes, read as Chrome shows them | No, unless the data sits in a script on the page, with REGEXEXTRACT | No | Not directly. It gets the raw HTML, but it can call the JSON URL the page loads |
| Pages behind your login Source 4, Source 5 | Yes, with your Chrome sign-in | No | No | Only if your code sends a cookie or token |
| Refresh Source 10, Source 14 | Daily on Free, up to hourly on Pro, while Chrome is open | Hourly, while the document is open | Hourly, while the document is open | Time-driven triggers, as often as every minute |
| Usage limits Source 10, Source 15 | Free: 1 scheduled task, 10M credits a month. Pro: 10 tasks, 250M credits. | A quota on the creator's account, no number published | A quota on the creator's account, no number published | 20,000 fetches and 90 minutes of trigger runtime a day; 6 minutes per run |
| Where the data goes | A new sheet BrowseWiz creates in your Drive | Any cell in your sheet | Any cell in your sheet | Wherever your code writes it |
| Price Source 10, Source 15 | Free, or Pro at $29/month (250M credits). Monthly billing only. | Free with a Google account; usage quota unpublished | Free with a Google account; usage quota unpublished | Free with a Google account, within the quotas above |
Which one to use
Keep IMPORTXML or IMPORTHTML if…
- The value shows in page source, signed out, even if only inside a script.
- Hourly updates while the sheet is open are enough.
- You want it free, in the cell, with no extension.
Use Apps Script if…
- You write JavaScript.
- The data comes from a JSON request you can see in the Network tab.
- Runs must happen with your computer off.
- The page is public, or you can send its token.
Use BrowseWiz if…
- The data appears only after scripts run or you sign in.
- You'd rather describe columns than write XPath, regex or code.
- Daily on Free, or hourly on Pro, while Chrome is open, is fresh enough.
Describe the data instead of writing XPath
BrowseWiz can't read the sheet that holds your formulas, so copy the URLs from the column that shows #N/A into your request:
Open each of these job postings and read the job title, the company and the date posted, as the page shows them: [paste the URLs from your IMPORTXML column]. Write them to a new sheet called Job postings, one row per URL, with the URL in a Source column, and note the date and time each was checked.
BrowseWiz shows a plan first. Approve it, grant tab access and sign in to Google once when it asks, and watch the sheet fill. Then click Update this sheet daily, or ask for weekdays at 8 AM, and approve the new plan. It becomes a scheduled task that keeps this sheet updated.
The rows it writes
The three career sites draw their job postings with JavaScript after the page loads, and their page source has no job data, not even in a script, so IMPORTXML returned #N/A. Google's job search reads postings from JobPosting structured data, which its guide puts in a <script type="application/ tag Source 16. If your job pages carry it, try the REGEXEXTRACT route above first.
| Job title | Company | Posted | Source | Checked at |
|---|---|---|---|---|
| Data Analyst | Lumen | Oct 6 | lumen.example/j/31 | Oct 7, 8:02 AM |
| Sales Lead | Orbit | Oct 2 | orbit.example/j/88 | Oct 7, 8:03 AM |
| QA Engineer | Tally | Sep 29 | tally.example/j/54 | Oct 7, 8:04 AM |
| UX Designer | Lumen | Sep 24 | lumen.example/j/27 | Oct 7, 8:04 AM |
Where BrowseWiz is the wrong tool
- Chrome has to be open. Schedules run only while Chrome is running.
IMPORTXMLand Apps Script don't need it. - Sign-ins expire. If a site signs you out, a scheduled run lands on the sign-in page until you sign in again in Chrome. You can ask BrowseWiz to write 'Signed out' in the row when that happens, so an old value doesn't pass for a fresh one.
- Not for volume. For thousands of URLs, proxies or captchas, use a hosted scraping service.
- Runs can differ. An AI agent reads the page each time, so values or rows can vary between runs. Ask for a source link per row, so you can check each value.
- Hourly is the fastest schedule, on Pro ($29/month) or Max. Free runs one task up to once a day.
- Site terms are yours. You're responsible for following each site's terms when you collect its data.
What BrowseWiz costs
Start on Free: it includes one daily scheduled task, one monitor and 10M credits a month. IMPORTXML is free; a BrowseWiz page read costs credits. On the pricing page's example, a 30,000-character page is about 7,500 input tokens and the reply about 500 output tokens, so one read costs 7,500 × 5 + 500 × 30 ≈ 52,500 credits. Each step of a run re-sends the chat, so credit use depends on how much page text each run reads.
Free
$0 / month
- 1 scheduled task, up to once a day
- 1 page monitor
- 10M credits a month
Pro
$29 / month
- Up to 10 scheduled tasks, as often as hourly
- Up to 30 page monitors
- 250M credits a month
Max
$79 / month
- Up to 10 scheduled tasks, as often as hourly
- Up to 30 page monitors
- 1B credits a month
Prices exclude VAT. See how credits are counted.
Questions
Usually because the value isn't in the HTML that Google's servers download. IMPORTXML doesn't run JavaScript or use your login Source 4, so script-loaded or signed-in content comes back empty, as #N/A Source 1. Check with View page source in an incognito window. If the value is in normal tags, fix the XPath. If it's inside a script, cut it out with REGEXEXTRACT Source 3.
If IMPORTXML shows stale data, delete the formula and add it again, or type over it with the same formula. Google says this forces a refresh, while closing and reopening the file doesn't. Left alone, IMPORTXML, IMPORTHTML and IMPORTDATA check for updates every hour while the document is open Source 10. For a fixed schedule, use an Apps Script time-driven trigger Source 14, or BrowseWiz, which writes fresh rows at a set time while Chrome is open.
No. IMPORTXML fetches the page from Google's servers without your browser session Source 4, so it gets the sign-in page, not your data. Apps Script can send a cookie or token if the site allows it, but that takes code and stored credentials. BrowseWiz reads the page in your own Chrome, where you're signed in, and writes the rows to a Google Sheet it creates.
Not among the built-in functions. Apps Script doesn't run the page's JavaScript either, but it can fetch the JSON the page loads Source 4. For marketplace product pages, the Amapulse add-on, formerly ImportFromWeb, reads JavaScript-rendered pages Source 12. Scraper extensions such as Instant Data Scraper read the page in your browser and export Excel or CSV files Source 17. BrowseWiz reads pages in your own Chrome, after scripts run and with your sign-in, and writes the rows to a new Google Sheet.
For a public page, use IMPORTHTML for a table or list, IMPORTXML with an XPath for anything else, and IMPORTDATA for a CSV file. They run on Google's servers and update hourly while the sheet is open Source 10. If the page needs JavaScript or a login, use Apps Script if you code, or BrowseWiz, which reads the page in your Chrome.
Google publishes no fixed number. It describes a usage quota, and past it cells show "Loading data may take a while because of the large number of requests" Source 10. Older guides quote a 50-formula cap. Use fewer formulas: one IMPORTHTML for a whole table instead of a column of IMPORTXML cells.
When the formula can't see the page, describe it
Add BrowseWiz to Chrome, paste your URLs and say which fields you want. Free includes one scheduled task.
Add to Chrome – it's freeSources
- Stack Overflow: Google's IMPORTXML returns "Imported content is empty" error (opens in a new tab)stackoverflow.com, checked
- Stack Overflow: Text inside <div> does not appear in Google Sheets using IMPORTXML (opens in a new tab)stackoverflow.com, checked
- Stack Overflow: How can I get the value of a <script> tag in Google Sheets? (opens in a new tab)stackoverflow.com, checked
- Stack Overflow: Scraping data to Google Sheets from a website that uses JavaScript (opens in a new tab)stackoverflow.com, checked
- Google Apps Script reference: Class UrlFetchApp (opens in a new tab)developers.google.com, checked
- Stack Overflow: ImportXML return empty (opens in a new tab)stackoverflow.com, checked
- MDN Web Docs: <tbody>, the Table Body element (opens in a new tab)developer.mozilla.org, checked
- Google Docs Editors Help: IMPORTXML (opens in a new tab)support.google.com, checked
- Stack Overflow: IMPORTHTML and IMPORTXML "Could not fetch URL", only on a specific webpage (opens in a new tab)stackoverflow.com, checked
- Google Docs Editors Help: Learn more about Import functions (opens in a new tab)support.google.com, checked
- Google Docs Editors Help: IMPORTHTML (opens in a new tab)support.google.com, checked
- Google Workspace Marketplace: Amapulse, formerly ImportFromWeb (opens in a new tab)workspace.google.com, checked
- Google Docs Editors Help: IMPORTRANGE (opens in a new tab)support.google.com, checked
- Google Apps Script: Installable triggers (opens in a new tab)developers.google.com, checked
- Google Apps Script: Quotas for Google Services (opens in a new tab)developers.google.com, checked
- Google Search Central: Job posting (JobPosting) structured data (opens in a new tab)developers.google.com, checked
- Chrome Web Store: Instant Data Scraper (opens in a new tab)chromewebstore.google.com, checked