~ / guides / How to Avoid Getting Blocked Scraping Walmart

How to Avoid Getting Blocked Scraping Walmart

RC
Russ Calder
Walmart data engineer · about the author
the short version
  • A plain requests.get on walmart.com/ip/<id> does not return product HTML. In my June 2026 test it returned HTTP 200 wrapping a 15 KB 'Robot or human?' page, and a real Chrome User-Agent changed nothing.
  • Walmart runs PerimeterX (now HUMAN) behind Akamai. It scores your IP reputation, TLS fingerprint, and a _px cookie, then serves a Press & Hold CAPTCHA when the score is too low.
  • The levers that actually move the result: residential US IPs, a slow request rate (under ~15-30 req/min per IP), a real browser that runs JavaScript, and respecting robots.txt.
  • Past a few thousand pages, rotating residential proxies plus a headless browser plus CAPTCHA handling is a full project. That is why most teams send a URL to a scraper API and get parsed JSON back.

To avoid getting blocked scraping Walmart, you first have to see how fast the block fires. I tried the lazy way: one requests.get against a live product page from my workstation. It never reached the product. The response was an HTTP 200 wrapping a 15 KB page titled “Robot or human?”, and I had not written a line of parsing yet. That redirect to a block page is the whole subject of this guide, because it is what almost everyone hits, and the standard advice (set a browser User-Agent) did nothing for me.

This guide covers the public walmart.com surface: product pages, search, reviews, and prices. It does not cover Walmart self checkout or in-store systems, which are closed point-of-sale environments with no public web endpoint. Below is exactly what I ran in June 2026, what Walmart returned, what triggers the block, and the setups that actually get product data back.

Why does Walmart block scrapers?

Walmart blocks scrapers because it runs PerimeterX (now HUMAN Bot Defender) behind an Akamai edge, and that system scores every request on IP reputation, TLS fingerprint, and browser signals before any product HTML is served. When the score falls below its threshold, Walmart redirects the request to a block page and the product never loads.

When I sent a request from an ordinary datacenter IP, Walmart bounced me to walmart.com/blocked?url=... (the original path base64-encoded) and served a “Robot or human?” interstitial carrying PerimeterX CAPTCHA scripts. PerimeterX merged with HUMAN in July 2022, and HUMAN Bot Defender shares device reputation across its protected sites, so a fingerprint flagged on one customer site arrives at Walmart already carrying low trust.

Here is what I measured against a live product page in June 2026. The three runs differ only by User-Agent:

RequestUser-AgentFinal URLStatusBody
GET /ip/587451676none/blocked?url=...20015,190-byte “Robot or human?” page
GET /ip/587451676full Chrome desktop string/blocked?url=...20015,190-byte “Robot or human?” page
GET /search?q=laptopfull Chrome desktop string/blocked?url=...20015,190-byte “Robot or human?” page

Two things stand out. The status code is 200, not 403 or 412, so a scraper that only checks for a 200 will parse the block page as if it were data. And the response was byte-for-byte identical with no User-Agent and with a real Chrome string, which tells you the User-Agent header is not what Walmart scored. The decision happened on the IP and the connection fingerprint, before Walmart looked at any header I could fake. The next section breaks down each signal it actually reads.

What triggers a Walmart block?

Walmart blocks on a stack of signals scored together by PerimeterX, and no single header controls the outcome. The four that carry the most weight are IP reputation, TLS and HTTP/2 fingerprint, the _px cookie state, and request behavior. A clean datacenter IP with a Python TLS signature and no PerimeterX cookie fails on all four at once, which is why my first request was blocked with nothing else wrong.

SignalWhat Walmart readsWhy a naive scraper fails
IP reputationWhether the IP is a datacenter range or a residential ISP, plus prior abuse historyCloud and VPS IPs are pre-scored as low trust
TLS / HTTP/2 fingerprintThe JA3/JA4 hash and HTTP/2 SETTINGS order of the clientrequests, urllib, and older aiohttp emit signatures no real browser sends
_px cookieA signed PerimeterX token set after a passed JavaScript challengeAn HTTP client never runs the JS, so the token is missing
BehaviorRequest rate, navigation pattern, mouse and timing telemetryBursts and headless automation read as non-human

The TLS fingerprint is the one that surprises people. The JA3 method hashes the exact ordering of the TLS Client Hello (cipher suites, extensions, elliptic curves), and a Python client produces a hash that no Chrome build ever emits. Walmart can flag the connection from that hash before a single byte of HTTP is exchanged, which is part of why my Chrome User-Agent was irrelevant.

The _px cookie is the second half. PerimeterX drops it after the browser solves a JavaScript challenge, and HUMAN’s own Bot Defender documentation describes a JavaScript sensor that scores client-side signals to issue that token. A request with no _px cookie and a datacenter IP scores low enough that Walmart skips straight to the CAPTCHA, which is the next thing worth understanding.

What is the Walmart “Press and Hold” CAPTCHA?

The Walmart “Press and Hold” CAPTCHA, sometimes written “Press & Hold”, is the PerimeterX human-verification challenge that appears on the “Robot or human?” block page, asking you to press and hold a button for a couple of seconds. The block page I received embedded the PerimeterX CAPTCHA scripts and a PerimeterX app token, which is the same challenge documented across PerimeterX-protected sites.

The press-and-hold gesture is a telemetry sample. While the button is held, the script records the micro-movements and timing jitter of a real hand and compares them against the flat, static signature an automated hold produces. That is why click-injection and naive Selenium scripts that “hold” for a fixed duration tend to fail the challenge: they produce a hold with no human jitter. Solving it reliably means driving a real browser with genuine input events, or routing the page through a service that already handles the challenge.

This matters for your approach because the CAPTCHA is downstream of the scoring described above. If your IP, fingerprint, and cookie state score high enough, the challenge never appears. The goal is to avoid triggering it in the first place, which the next sections cover for both the do-it-yourself route and the API route.

How do you avoid getting blocked when scraping Walmart?

You avoid getting blocked scraping Walmart by raising your trust score on the signals PerimeterX actually reads: use residential US IPs, run a real browser that executes JavaScript, slow your request rate, and stay within the paths Walmart’s robots.txt permits. These are the levers that moved the result in my testing, in rough order of impact.

The honest tradeoff is maintenance. Doing all of this yourself means buying and rotating a residential proxy pool, running headless browsers at scale, refreshing _px tokens, and retrying the requests that still draw a CAPTCHA. That becomes a standing engineering project once you pass a few thousand pages, which is the reason most teams hand the blocking problem to a scraper API.

How do you scrape Walmart without managing proxies?

You scrape Walmart without managing proxies by sending the target URL to a scraper API that runs the residential proxy rotation, the real browser, and the PerimeterX handling on its own servers, then returns parsed JSON. You send one request and get structured product data, with no _px cookie to maintain and no “Robot or human?” page to debug.

ChocoData works this way. You pass a Walmart product URL and your API key, and the rotation and challenge handling happen server-side. The request shape is a single GET:

curl "https://chocodata.com/api/v1/walmart/product?url=https://www.walmart.com/ip/587451676&api_key=$CHOCO_API_KEY"

The Python version is the same call, and unlike my naive script earlier, the blocking is handled before the response comes back:

import requests
import os

# Get a key at https://app.chocodata.com/sign-up
CHOCO_API_KEY = os.environ["CHOCO_API_KEY"]

resp = requests.get(
    "https://chocodata.com/api/v1/walmart/product",
    params={
        "url": "https://www.walmart.com/ip/587451676",
        "api_key": CHOCO_API_KEY,
    },
    timeout=60,
)
resp.raise_for_status()
data = resp.json()

# Parsed product fields come back as JSON. The CAPTCHA is handled upstream.
print(data["title"], data["price"])

The same pattern covers the other Walmart targets that draw blocks on their own: search results, reviews, and price monitoring. For a one-off pull of a few hundred records you can build the residential-proxy-and-browser stack yourself. For continuous collection across thousands of pages, offloading the rotation and the CAPTCHA is usually the cheaper path once you price in your own time.

One caveat before you scale either route: avoiding the block is a technical problem, and staying compliant is a separate one. US courts have narrowed the Computer Fraud and Abuse Act around public data in Van Buren v. United States (2021) and the Ninth Circuit’s hiQ v. LinkedIn rulings, yet Walmart’s Terms of Use still prohibit automated collection, which keeps contract and tort claims on the table.

If you want to see the raw request-building approach first, my Walmart Python guide walks through the parsing, and before you collect anything at scale it is worth reading where the legal line sits in is scraping Walmart legal.

FAQ

Why do I get a 'Robot or human?' page with a 200 status code?

Walmart serves the block as an HTTP 200 page. In my test the request to a product URL was redirected to walmart.com/blocked?url=... with a 'Robot or human?' title and PerimeterX CAPTCHA scripts, and the status line read 200. The 200 status means a naive scraper that only checks status_code == 200 will happily parse the block page as if it were product data.

Does changing the User-Agent stop Walmart from blocking me?

No. I sent the same product request with no User-Agent, with a full Chrome desktop string, and the response was byte-for-byte identical: the same 15,190-byte 'Robot or human?' page both times. PerimeterX scores the datacenter IP and the TLS fingerprint, so the User-Agent header alone does not change the outcome.

How many requests can I send to Walmart before getting blocked?

There is no published limit. Field testing across scraping vendors puts the soft-block threshold around 15 requests per minute per IP on search and roughly 30 on product pages, lower if the IP is a datacenter range. A single fresh datacenter IP often gets blocked on the first request, which is what happened in my test.

Is scraping Walmart legal?

Scraping publicly visible pages sits in a defensible zone in the US after hiQ v. LinkedIn and Van Buren v. United States narrowed the CFAA. Walmart's Terms of Use still prohibit automated collection, so contract and tort claims remain the real exposure. I cover this in detail in the legal guide linked below.

Can I scrape Walmart self-checkout or in-store data this way?

No. Walmart scraping covers public walmart.com pages: product, search, reviews, and prices. Self-checkout and in-store systems are closed point-of-sale environments with no public web endpoint, so none of the proxy or browser techniques here apply to them.

RC
Russ Calder
I've built Walmart data pipelines for years. On walmartscraperapi.com I run Walmart scraping methods against live pages and publish what actually holds up.