WooCommerce Checkout Stuck Loading? Common Causes and Fixes
A WooCommerce checkout page that keeps loading forever is more than an inconvenience. It stops customers from placing orders, blocks payment methods from loading, and quietly drains revenue while the rest of the site looks completely normal. The symptom is usually simple: the customer reaches checkout, enters their details, and the order review section just keeps spinning. Sometimes the payment methods never appear, sometimes the Place Order button goes unresponsive, and sometimes nothing obvious happens at all.
The hard part is that checkout loading issues can come from several different layers: plugin conflicts, theme issues, caching, AJAX failures, PHP warnings, payment gateway conflicts, server-level rewrites, security and firewall rules, broken JavaScript, or invalid JSON responses. That is why the best fix is not to randomly disable plugins or rebuild checkout. The best fix is to find where the checkout request actually breaks.
This guide explains why WooCommerce checkout gets stuck loading, how to debug it properly, and what to check before making bigger changes.
What Does “WooCommerce Checkout Stuck Loading” Usually Mean?
WooCommerce checkout is dynamic. When a customer enters billing details, changes country, adds a coupon, selects shipping, or chooses a payment method, WooCommerce sends background requests to update the order review. Those requests run through AJAX, and a common one looks like this:
/?wc-ajax=update_order_review
This request updates the order total, tax, shipping methods, payment methods, coupon calculations, cart fragments, and checkout notices. If it fails or returns the wrong response, the checkout page can keep loading forever. The spinner is rarely the real problem. It is only the visible symptom. The actual cause is usually one of these:
- The request never completes
- The request returns an error
- The request returns HTML instead of JSON
- The request is blocked by security rules
- PHP warnings are injected into the response
- JavaScript cannot process the returned data
- Caching serves stale or invalid content
Common Symptoms of a Broken WooCommerce Checkout
A checkout loading issue shows up in different ways. You may see an endless spinner in the order review area, payment methods that never appear, a Place Order button that will not click, a page that reloads without placing the order, shipping methods that do not update, an unresponsive coupon section, fields behaving strangely, console errors, payment gateway errors, a blank order review box, or an order received page that is never reached. Customers often report that “payment is not working,” but the gateway may not be the real problem. Checkout can break before the payment step even begins.
First Rule: Do Not Assume It Is the Payment Gateway
When checkout fails, the payment plugin gets blamed first. That is understandable, since checkout and payment happen close together. But WooCommerce checkout can break well before payment is involved. Before blaming Stripe, PayPal, Mollie, Klarna, Vipps, or any other gateway, check whether the core checkout AJAX request works. If update_order_review fails, the gateway may only be a downstream symptom. A quick test:
- Temporarily enable a basic payment method such as bank transfer.
- Disable the main payment gateway.
- Test checkout again.
- Check whether the spinner still appears.
If checkout still hangs with a basic method enabled, the issue is probably not the payment provider.
Cause 1: WooCommerce AJAX Returning the Wrong Response
This is one of the most important causes. WooCommerce expects checkout AJAX responses to be valid JSON, but sometimes the server returns a normal HTML page instead. In the browser Network tab you might see:
Status: 200 OK
Content-Type: text/html
At first, 200 OK looks successful. But if WooCommerce expects JSON and receives HTML, the checkout JavaScript cannot process the response, and the result is usually an infinite spinner. If you open the response and see a full webpage like this, there is a problem:
<!DOCTYPE html>
<html>
<head>
<title>...</title>
</head>
<body>
...
</body>
</html>
That means something is intercepting the AJAX request. Possible culprits include an .htaccess rewrite, a caching layer, a redirect rule, a security plugin, maintenance mode, a login redirect, custom PHP output, a server firewall page, or a theme or plugin conflict. This is exactly why checking the response body is critical.
Cause 2: Caching Checkout, Cart, or AJAX Requests
Cart and checkout must stay dynamic. They should never be served as static cached pages. When caching is misconfigured, WooCommerce can show stale cart data, broken totals, invalid session data, or endless loading. Common sources include a WordPress cache plugin, LiteSpeed Cache, WP Rocket, server cache, Cloudflare, a CDN, browser cache, object cache, or an optimization plugin. The important paths to exclude from full-page caching are:
/cart/
/checkout/
/my-account/
/?wc-ajax=
Also watch for cookies that signal an active WooCommerce session:
woocommerce_items_in_cart
woocommerce_cart_hash
wp_woocommerce_session_
When these cookies are present, the visitor is in a dynamic session and a full-page cache should not serve everyone the same static page.
What to check
- Is checkout excluded from cache?
- Is cart excluded from cache?
- Is
wc-ajaxexcluded? - Is Cloudflare caching dynamic pages?
- Is server-level cache active even when the plugin is disabled?
- Is mobile cache serving a separate broken version?
- Is JavaScript minification delaying WooCommerce scripts?
A cache plugin can be off while server or CDN cache still affects the page, so always check every layer.
Cause 3: PHP Warnings Breaking AJAX Responses
WooCommerce AJAX responses need to be clean. If PHP warnings or notices are printed into the response, the JSON breaks. A typical warning:
Warning: Undefined array key "redirect_cache"
This happens when custom code reads an array key without checking that it exists:
$id = $_SESSION['redirect_cache'];
A safer version:
$id = isset($_SESSION['redirect_cache']) ? (int) $_SESSION['redirect_cache'] : 0;
Even a small warning can pollute an AJAX response. On a normal page the warning appears above the content; inside an AJAX call, it can make the whole response invalid.
What to check
Open the AJAX response body and look for PHP warnings, notices, deprecation messages, plugin error output, HTML before the JSON, debug output, stray var_dump() or print_r(), or an accidental echo. If any appear during checkout AJAX, fix the source and stop the frontend from displaying errors. On production, debug output should go to a log, not to visitors:
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
@ini_set('display_errors', 0);
This does not replace fixing the code, but it stops warnings from breaking frontend responses.
Cause 4: JavaScript Errors on the Checkout Page
WooCommerce checkout leans heavily on JavaScript. If another script throws an error before the checkout scripts finish, checkout can stop updating. Common causes include a theme script error, a custom checkout script, broken minified JS, delayed or deferred WooCommerce scripts, an optimization plugin conflict, a missing dependency, a jQuery conflict, browser extension noise, or a third-party tracking script.
What to check
Open DevTools and check the Console tab for red errors related to:
checkout
wc_checkout_params
update_order_review
jQuery
payment_method
fragments
Not every console error matters. Some browser extensions generate unrelated noise. For checkout issues the Network tab is usually more revealing than the Console, but JavaScript errors are still worth reviewing.
Cause 5: Theme or Template Conflicts
Checkout can break when a theme overrides WooCommerce templates incorrectly. Watch for outdated template overrides, missing checkout hooks, a removed notices section, a custom layout that hides required elements, custom JavaScript interfering with WooCommerce events, a missing wp_footer() or wp_head(), incorrect form markup, or CSS hiding payment methods or buttons. WooCommerce templates rely on hooks, so if a theme removes or moves important ones, checkout becomes unstable.
What to check
Go to:
WooCommerce → Status → Templates
Check whether any templates are outdated, and inspect whether the active theme has overrides inside:
your-theme/woocommerce/
If checkout templates are overridden, compare them with the current WooCommerce versions. A quick test is to switch temporarily to a default theme like Storefront and test checkout again. If it works with Storefront, the issue is likely in the theme or its template overrides.
Cause 6: Plugin Conflicts
Plugin conflicts are common, but they should be tested methodically rather than by guesswork. Plugins that often affect checkout include payment gateways, shipping plugins, checkout field editors, multilingual plugins, currency switchers, tax and VAT plugins, security plugins, cache and optimization plugins, custom snippet plugins, anti-spam plugins, analytics and tracking plugins, and invoice or order plugins.
How to test safely
On a staging site, deactivate all non-essential plugins except WooCommerce, then test checkout. If it works, reactivate plugins one by one until the issue returns, starting with the ones most likely to be involved:
- Payment plugins
- Shipping plugins
- Checkout field plugins
- Cache and optimization plugins
- Security plugins
- Custom snippets
- Tracking and analytics plugins
Avoid doing this directly on a busy live store unless you have no other option and traffic is low.
Cause 7: Server-Level Rewrite or Redirect Rules
Sometimes checkout breaks because WordPress never receives the request correctly, through .htaccess, Nginx, LiteSpeed, or CDN rules. A rewrite can accidentally intercept a request like:
/?wc-ajax=update_order_review
When that happens, WooCommerce may receive a static homepage, a redirect, a 403 page, a cached HTML file, a login page, or a firewall message, which creates endless loading even though WooCommerce itself is fine. This is precisely what happened in one checkout case we traced to an .htaccess rewrite, where a static-homepage rule was catching the WooCommerce AJAX request.
What to check
Review your .htaccess, Nginx rules, LiteSpeed rules, Cloudflare page rules, redirect plugin rules, server cache rules, and security firewall logs. Be especially careful with anything affecting:
/
/checkout/
/cart/
/my-account/
/?wc-ajax=
A small server-level rule can break a large part of WooCommerce.
Cause 8: Security Firewall or ModSecurity Blocking Requests
Security layers can block checkout requests when they look suspicious, because those requests carry customer data, address fields, payment metadata, AJAX payloads, nonce values, and dynamic session data. A blocked request may return:
403 Forbidden
or a branded security page. Sometimes it still returns 200 OK with a challenge page, which is even harder to spot.
What to check
In the Network tab, inspect the failed request and look for a 403, 406, or 500 status, firewall HTML, a captcha or challenge page, or messages like “Access denied” or “Not acceptable.” If you suspect this, check the hosting firewall logs or ask the host whether ModSecurity blocked the request.
Cause 9: Checkout Field Customization Problems
Custom checkout fields can break checkout when they are added incorrectly: required fields missing validation, invalid field keys, unsanitized custom fields, address fields removed the wrong way, badly renamed billing or shipping fields, a conflict with a checkout field editor, or JavaScript expecting a field that no longer exists. Removing a field, for example, should be done through checkout field hooks, not by deleting markup by hand:
add_filter('woocommerce_checkout_fields', function($fields) {
unset($fields['billing']['billing_address_2']);
if (isset($fields['billing']['billing_phone'])) {
$fields['billing']['billing_phone']['required'] = true;
}
return $fields;
});
This is far safer than editing WooCommerce core files or hiding fields with CSS alone.
Cause 10: Missing WooCommerce Pages or Wrong Page Settings
WooCommerce depends on specific pages for cart, checkout, account, and terms. If they are missing or wrongly assigned, checkout behaves unpredictably. Check:
WooCommerce → Settings → Advanced
Confirm the Cart page, Checkout page, My account page, and Terms and conditions page (if used) are assigned correctly. Also confirm the checkout page contains the correct WooCommerce checkout block or shortcode, which depending on the setup may be:
[woocommerce_checkout]
or the WooCommerce Checkout block.
Cause 11: REST API or admin-ajax Issues
WooCommerce and WordPress use background requests constantly. If the REST API or AJAX endpoints are blocked, cart and checkout behaviour can break. Check the REST API at:
/wp-json/
and AJAX requests such as:
/wp-admin/admin-ajax.php
/?wc-ajax=...
Possible blockers include a security plugin, a firewall, a server rule, a malformed redirect, broken SSL, mixed content, a caching layer, or an incorrect site URL. If admin-ajax or the REST API is blocked, plenty of WordPress features fail beyond checkout.
How to Debug WooCommerce Checkout Loading Properly
Here is a practical process.
Step 1: Reproduce the issue
Open checkout in an incognito browser and run the full path, watching the order review:
Add product → Cart → Checkout → Fill fields → Watch order review
Confirm exactly when the spinner starts.
Step 2: Open browser DevTools
Go to the network requests:
Network → Fetch/XHR
Reload checkout and watch for:
?wc-ajax=update_order_review
Step 3: Check the status code
Look for 200, 302, 403, 404, or 500. Each one tells a different story.
Step 4: Check response headers
Pay attention to:
Content-Type
Cache-Control
Server
Location
If Content-Type is text/html when JSON is expected, inspect the response body.
Step 5: Check the response body
Look for a full HTML page, a PHP warning, a login page, a security block, a redirect page, invalid JSON, or a cached homepage.
Step 6: Check the Console
Look for relevant JavaScript errors, and ignore obvious browser extension noise unless it directly affects checkout scripts.
Step 7: Check the logs
Review the WooCommerce logs, the PHP error log, the WordPress debug log, the server error log, and any firewall or ModSecurity log.
Step 8: Test theme and plugin conflicts
Use staging where possible. Switch theme and reduce plugins to isolate the issue.
What a Healthy WooCommerce Checkout Request Should Look Like
A healthy checkout AJAX request should complete quickly, return the correct response format, avoid returning full HTML unexpectedly, contain no PHP warnings, not be cached incorrectly, not be blocked by a firewall, trigger the order review update, allow payment method selection, and let the order proceed. Requests do not need to look identical across stores, but the response has to be valid for WooCommerce to process.
What Not to Do
When checkout is stuck loading, avoid these:
- Rebuilding checkout immediately
- Editing WooCommerce core files
- Hiding errors without checking the cause
- Disabling random plugins on a live store during peak traffic
- Assuming the payment gateway is the cause
- Clearing cache repeatedly without checking the Network response
- Replacing the theme before checking AJAX
- Adding more snippets to “force” checkout to work
- Ignoring PHP warnings because “the page still loads”
- Changing
.htaccesswithout testing dynamic requests
The fastest fix usually comes from identifying the exact failing request.
When to Ask for Help
It is worth bringing in expert help when:
- Checkout keeps spinning after basic troubleshooting
update_order_reviewreturns HTML instead of JSON- Payment methods disappear
- The Place Order button does not respond
- Checkout works only sometimes
- PHP warnings appear on checkout
- Checkout breaks after adding AI-generated code
- Cache exclusions do not solve the issue
- Theme and plugin conflict testing does not reveal the cause
- Server rules or firewall behaviour look suspicious
Checkout issues are usually fixable, but guessing wastes time and can create new problems.
Final Thoughts
A WooCommerce checkout stuck loading is rarely a mystery once you follow the request path. The trick is to stop staring at the spinner and start checking what the server actually returns to WooCommerce. In many cases the problem is not WooCommerce itself but something around it: caching, server rewrites, invalid PHP output, security rules, theme overrides, JavaScript conflicts, or plugin behaviour. The safest fix is the one that restores WooCommerce’s native flow rather than replacing it unnecessarily.
If your WooCommerce checkout is stuck loading, Webnorly can review the issue, identify the failing request, and restore the checkout flow safely. Send us the issue and we’ll trace it from the spinner back to the request that’s actually breaking.
Related articles
AI-Generated WordPress Code Review Checklist
AI can generate WordPress code in seconds, but a snippet that looks correct can still break checkout, redirects, AJAX, or plugin compatibility. This 20-point checklist gives you a practical way to review AI-generated code before it touches functions.php, .htaccess, or WooCommerce, covering placement, hooks, sanitization, escaping, security, performance, and a rollback plan.
Read articleHow to Convert Static HTML into a WordPress Theme Without Breaking the Site
AI can generate a beautiful static HTML site in minutes, but forcing it into WordPress with file uploads and .htaccess rewrites breaks routing, plugins, forms, and checkout. This 18-step guide shows how to convert static HTML into a proper WordPress theme, with header, footer, enqueued assets, menus, and native WooCommerce intact.
Read articleBefore You Paste AI-Generated PHP into WordPress, Check These Things
AI can write a WordPress PHP snippet in seconds, but pasted in without review it can trigger warnings, break checkout AJAX, cause a white screen, or create redirect loops. Here are the 14 things to check before you paste AI-generated PHP into WordPress, from variable checks and sanitization to hooks, nonces, and a safer placement strategy, with before-and-after code.
Read article