When WooCommerce checkout keeps loading, first identify whether it is waiting before submission, during a request or while processing the response. A spinner alone does not locate the failure. Keep one recorded attempt and correlate it with the order and payment state.
Do not keep pressing the button. First confirm whether WooCommerce created an order or the gateway took payment, because repeated attempts can produce duplicate orders or charges.
Preserve one failed attempt
Record the exact time, customer email, cart contents, payment method, browser and displayed total. Use a controlled test product and a gateway test mode when available. If the fault affects live customers, check recent orders and the payment provider before reproducing it.
Match the attempt with recent orders and their actual status. A checkout-draft record is temporary; it does not establish a completed submission or charge. Compare the request method, time and payment evidence. The WooCommerce order-status reference explains the distinction.
Inspect the checkout request
Open Network before the controlled attempt. For classic checkout, inspect the POST containing wc-ajax=checkout. For the Checkout block, identify the final POST to the Store API checkout route, such as /wp-json/wc/store/v1/checkout. Record the method as well as the path: a data lookup is a different operation.
If there is no final submission yet, check pending totals or shipping work. The documented Checkout block flow includes a calculating state that can disable Place Order. Diagnose the waiting operation before changing the button.
Request path examples:
Classic: POST /?wc-ajax=checkout
Block: POST /wp-json/wc/store/v1/checkout
Capture: method, status, timing, content type and response body.
A 500 response points towards PHP or server failure. A 403 may come from a firewall or security rule. A request left pending suggests an upstream timeout, locked PHP worker or slow external call. A 200 response containing HTML instead of JSON often indicates a warning, login page or cached error contaminating the response.
What six offline response fixtures can tell you
We ran six self-authored fixtures through a small local response interpreter. Four carried HTTP 200 and led to four different next steps. This was an offline teaching exercise: no store, customer, order or payment service was contacted. The fixture names below describe examples, not failures measured on a client’s shop.
- No submission recorded: there is no final request in the sample. Check the capture and pre-submission state before investigating a server response.
- Classic validation response: HTTP 200 with
result: failureis readable JSON containing an application rejection. - Classic HTML response: HTTP 200 with a maintenance page cannot be interpreted as the expected JSON response.
- Block draft lookup: GET with HTTP 200 and
status: checkout-draftdescribes checkout data, rather than proof of a successful final submission. - Block offline-method response: POST with HTTP 200,
status: on-holdandpayment_status: successneeds interpretation for that method. It does not prove a card capture. - Access rejection: HTTP 403 remains an HTTP error even when the body is valid JSON. Read the actual error and correlate the request before assigning a cause.
Two authored HTTP 200 fixtures:
Classic POST: {"result":"failure"}
Block GET: {"status":"checkout-draft"}
Same HTTP status; different method, body and next check.
To repeat the exercise, record method, path, HTTP status and body separately, then classify the payload before deciding what happened to the transaction. Our interpreter deliberately never marks a real capture as proven from these fixtures. Use the classic checkout response source and Store API reference to check your installed flow; extensions and versions can change the details.
Correlate PHP and WooCommerce logs
Check WooCommerce > Status > Logs and the hosting PHP error log for the same timestamp. Temporarily enable WordPress debug logging only if you can prevent public error display and personal data exposure.
Do not treat every old warning as the cause. Match the request time, file and call stack. Fatal errors in a payment plugin, checkout-field extension or theme override are stronger evidence than unrelated scheduled-task notices.
Separate gateway delay from checkout failure
Repeat in a safe test environment with an offline payment method such as Direct bank transfer. If offline checkout completes but the normal gateway spins, inspect gateway credentials, API reachability, web application firewall rules and the gateway log.
If every method fails, focus on WooCommerce, PHP, sessions and shared checkout customisation. Never switch a production gateway into test mode without understanding how it affects real customers.
Check sessions, cache and background calls
Exclude Cart, Checkout and My account from full-page cache. Confirm that WooCommerce cookies survive between the product, cart and checkout pages. Cloudflare and WordPress cache rules must not serve one visitor’s checkout state to another.
Use a private window for a clean session, but retain the failing session separately. Clearing every session immediately destroys useful evidence and logs out customers without proving the cause.
Test JavaScript without hiding the server problem
Inspect the Console for the first error, not the longest cascade. A consent tool, address autocomplete, analytics tag or checkout-field script may intercept submission. Test by disabling one suspected integration in staging or with a controlled request, never by deactivating random plugins on the live store.
The browser may show a script error because the server returned invalid content. Read the checkout response before concluding that JavaScript is the root cause.
Repair and verify the complete transaction
Apply the smallest evidence-backed correction: update or roll back one incompatible component, repair the fatal PHP path, correct caching, increase a genuinely exhausted resource, or fix the gateway connection.
Then verify guest and logged-in checkout, mobile and desktop, taxes, shipping, coupons, stock reduction, order emails, gateway status and the thank-you page. Confirm in both WooCommerce and the provider that the test produced exactly one order and one payment.
Urgent repair is complete only when ordering works and no uncertain transactions remain. Recurring monitoring should alert on checkout errors, gateway webhook failures and abnormal order-status patterns before another spinner becomes lost revenue.
For a checkout repair assessment, send the checkout type, payment method, affected URL and time of the failed attempt. If the provider already shows a charge, follow payment succeeded but the order remains pending before authorising another attempt.
To commission an investigation, use the checkout diagnostic brief and evidence template for 2027 to organise the known facts, missing checks and authorised next step.