jQuery ajaxStop Event

Beginner
⏱️ 12 min read
📚 Updated: Jul 2026
🎯 5 Examples
🚀 5 Try-it labs
Ajax events

What You’ll Learn

The ajaxStop event fires when the last qualifying jQuery Ajax request completes — and only when no other global requests remain active. This tutorial covers binding on document with .on("ajaxStop"), pairing with ajaxStart for loading indicators, opting out with global: false, and comparing ajaxStop with per-request events like ajaxComplete.

01

Global

AjaxEvent

02

document

Bind target

03

Last only

Not every call

04

ajaxStart

Pair for UI

05

global:false

Opt out

06

Since 1.7

.on() API

Introduction

When your page loads data with $.ajax(), $.get(), or .load(), jQuery broadcasts lifecycle events to listeners on document. The ajaxStop event is your “all activity finished” hook — it fires once when the last active global Ajax request completes, giving you a single place to hide a loading spinner or re-enable navigation.

jQuery tracks how many global Ajax calls are in progress. When the count drops to zero, jQuery triggers ajaxStop. That pairing with ajaxStart — which fires when the count goes from 0 to 1 — makes ajaxStop ideal for page-wide loading UI without counting individual requests yourself. If the last outstanding request is cancelled via beforeSend returning false, ajaxStop still fires when no requests remain active.

Understanding the ajaxStop Event

ajaxStop is classified as an AjaxEvent — a global event triggered by jQuery’s Ajax transport, not a DOM event on a specific element. Whenever the last active global Ajax request finishes and no others remain, jQuery triggers ajaxStop on document. Handlers are simple callbacks with no extra arguments — unlike ajaxComplete, you do not receive jqXHR or settings.

The handler runs at the very end of global Ajax activity — after ajaxComplete on the last request, and after any success or error handlers. For per-request logging or response inspection, use ajaxComplete instead. For hiding the spinner when all requests finish, bind ajaxStop alongside ajaxStart.

💡
Beginner Tip

Bind once: $(document).on("ajaxStart", showSpinner) and $(document).on("ajaxStop", hideSpinner). Three parallel $.get() calls trigger ajaxStart once and ajaxStop once — not three times each.

📝 Syntax

The modern jQuery API for the ajaxStop global event:

1. Bind a handler — $(document).on("ajaxStop" [, handler]) (since 1.7)

jQuery
$( document ).on( "ajaxStop", handler )
  • handler — function invoked when the last global Ajax request completes: function() { ... } — no jqXHR or settings arguments.
  • Fires only when no global requests remain in progress.
  • Must attach to document since jQuery 1.9.

2. Official demo — document handler + .load() on click

jQuery
$( document ).on( "ajaxStop", function() {
  $( ".log" ).text( "Triggered ajaxStop handler." );
} );
$( ".trigger" ).on( "click", function() {
  $( ".result" ).load( "ajax/test.html" );
} );

3. Official demo — hide loading message

jQuery
$( document ).on( "ajaxStop", function() {
  $( "#loading" ).hide();
} );

Pair with ajaxStart to show the indicator when the first request begins.

4. Unbind — $(document).off("ajaxStop" [, handler])

jQuery
$( document ).off( "ajaxStop" );              // remove all ajaxStop handlers
$( document ).off( "ajaxStop", myHandler );   // remove one handler

5. Deprecated method — .ajaxStop(handler)

jQuery
// Deprecated — use .on("ajaxStop") instead
$( document ).ajaxStop( function() {
  $( "#loading" ).hide();
} );

The old .ajaxStop(handler) binding method still works but is deprecated since jQuery 3.5. Migrate to $(document).on("ajaxStop", handler). This page covers the ajaxStop event — not the deprecated shorthand method.

Return value

  • .on("ajaxStop", handler) returns the jQuery object (document wrapped) for chaining.
  • Handler return values are ignored by jQuery’s global Ajax event system.

⚡ Quick Reference

GoalCode
Bind global stop handler$(document).on("ajaxStop", fn)
Handler signaturefunction() — no extra arguments
When it firesLast global request completes (none remain active)
Show spinner when activity begins$(document).on("ajaxStart", fn)
Per-request hook$(document).on("ajaxComplete", fn)
Opt out of global events$.ajax({ url: "/x", global: false })
Remove handlers$(document).off("ajaxStop")

📋 ajaxStop vs ajaxComplete vs ajaxStart

Three global events at different points in the lifecycle — choose the scope that matches your task.

ajaxStop
last only

Fires once when the last active global request finishes — hide page-wide loading UI

ajaxComplete
every call

Fires after each request finishes — success or error — with jqXHR and settings

ajaxStart
first only

Fires once when the first global request begins — show loading UI

ajaxSend
every call

Fires before each individual request is sent — receives jqXHR and settings

Global event order: ajaxStartajaxSendajaxSuccess | ajaxErrorajaxCompleteajaxStop. ajaxStart and ajaxStop bracket the batch; ajaxSend and ajaxComplete fire per request.

Examples Gallery

Examples 1 and 2 follow the official jQuery API documentation. Examples 3–5 extend those patterns with parallel requests, global: false, and an ajaxStart + ajaxStop loading pair with ajaxStop as the focus. Use the Try-it links to run each snippet in the browser.

📚 Official Patterns

Document-level handlers that observe when global Ajax activity ends.

Example 1 — Official Demo: Document Handler + .load() on Click

Attach ajaxStop on document, then trigger an Ajax request with .load() when the user clicks .trigger.

jQuery
$( document ).on( "ajaxStop", function() {
  $( ".log" ).text( "Triggered ajaxStop handler." );
} );
$( ".trigger" ).on( "click", function() {
  $( ".result" ).load( "ajax/test.html" );
} );
Try It Yourself

How It Works

.load() uses $.ajax() internally, so it triggers global Ajax events. When the request finishes and no others are active, ajaxStop fires once.

Example 2 — Official Demo: Hide #loading on ajaxStop

The classic loading-indicator pattern from the jQuery API docs — hide a message whenever all Ajax activity ends.

jQuery
$( document ).on( "ajaxStop", function() {
  $( "#loading" ).hide();
} );
Try It Yourself

How It Works

ajaxStop is designed for this use case — one handler hides UI when global activity ends. Without ajaxStart, you need another way to show the indicator when requests begin.

Example 3 — Parallel Requests: ajaxStop Fires Once

Launch two $.get() calls at once — ajaxStop runs only when the last one finishes, not twice.

jQuery
var stopCount = 0;
$( document ).on( "ajaxStop", function() {
  stopCount++;
  $( "#stop-count" ).text( stopCount );
} );
$( "#run-two" ).on( "click", function() {
  $.get( "https://jsonplaceholder.typicode.com/posts/1" );
  $.get( "https://jsonplaceholder.typicode.com/posts/2" );
} );
Try It Yourself

How It Works

jQuery tracks active global requests internally. The second parallel call keeps the count above zero until it also finishes, so ajaxStop fires once when both are done. Use ajaxComplete if you need a hook for every individual finished request.

📈 Opt-Out & ajaxStart Pairing

global: false and the complete loading-indicator pattern with ajaxStart.

Example 4 — global: false — Event Does Not Fire

Requests with global: false skip all global Ajax events, including ajaxStop.

jQuery
var stopCount = 0;
$( document ).on( "ajaxStop", function() {
  stopCount++;
  $( "#log" ).append( " ajaxStop (" + stopCount + ")" );
} );
$( "#global-btn" ).on( "click", function() {
  $.get( "https://jsonplaceholder.typicode.com/posts/1" );
} );
$( "#private-btn" ).on( "click", function() {
  $.ajax( {
    url: "https://jsonplaceholder.typicode.com/posts/2",
    global: false
  } );
} );
Try It Yourself

How It Works

Setting global: false opts that request out of ajaxStart, ajaxSend, ajaxComplete, and ajaxStop. Use it for background polling or third-party widgets that should not affect your page-wide loading UI.

Example 5 — Pair ajaxStart + ajaxStop for Loading UI

Show a spinner when global activity begins and hide it when the last request finishes — the canonical loading-indicator pattern with ajaxStop as the hide hook.

jQuery
$( document ).on( "ajaxStart", function() {
  $( "#loading" ).show();
} );
$( document ).on( "ajaxStop", function() {
  $( "#loading" ).hide();
} );
$( "#run-two" ).on( "click", function() {
  $.get( "https://jsonplaceholder.typicode.com/posts/1" );
  $.get( "https://jsonplaceholder.typicode.com/posts/2" );
} );
Try It Yourself

How It Works

ajaxStart and ajaxStop are designed as a pair. You do not need to count requests — jQuery tracks active global calls and fires ajaxStop only when the count returns to zero. This example highlights ajaxStop as the hide hook.

🚀 Common Use Cases

  • Loading spinners — hide a page-wide indicator when the last Ajax request completes; show it on ajaxStart.
  • Re-enable navigation — unlock buttons or allow form submission when global Ajax activity ends.
  • Activity badges — clear a “Loading…” status flag once per batch instead of per request.
  • Analytics — record when a page-wide Ajax session ended (pair with ajaxStart for duration).
  • Third-party isolation — set global: false on widget requests so they do not delay your ajaxStop UI.
  • Testing — assert that a test harness left the “loading” state exactly once per batch.

🧠 Global Ajax Event Order

1

ajaxStart

First active global request begins — show loading UI. Fires once per batch, not per request.

ajaxStart
2

ajaxSend

Before each individual request is sent — all registered handlers execute with jqXHR and settings.

ajaxSend
3

ajaxSuccess or ajaxError

Outcome-specific global event — success handler or error handler runs per request.

success | error
4

ajaxComplete

Always runs after step 3 for each request — finished, success or error.

ajaxComplete
5

ajaxStop

Last active global request finished — hide loading UI. Fires once when the batch completes.

📝 Notes

  • Bind with $(document).on("ajaxStop", handler) since jQuery 1.7 — not the deprecated .ajaxStop(handler) method.
  • Since jQuery 1.9, attach global Ajax handlers to document — not window.
  • Fires only when no global requests remain in progress — not for every individual call.
  • Handler receives no extra arguments — use ajaxComplete for jqXHR and settings.
  • Always pair with ajaxStart when showing loading UI — otherwise nothing shows the indicator at the start.
  • Requests with global: false do not trigger ajaxStop and do not count as active global requests.
  • Multiple parallel requests share one ajaxStart / ajaxStop pair.
  • If the last outstanding request is cancelled via beforeSend returning false, ajaxStop still fires when no requests remain active.

Browser Support

The ajaxStop event is a jQuery global Ajax event — not a native DOM event. It works wherever jQuery’s Ajax transport runs: all browsers supported by your jQuery version. Bind with .on("ajaxStop") since 1.7; attach handlers to document since 1.9.

jQuery 1.7+

jQuery ajaxStop event

Supported in jQuery 1.x, 2.x, and 3.x across all modern browsers and IE with supported jQuery builds. Requires jQuery Ajax — requests made with fetch() or axios do not trigger jQuery global events.

100% With jQuery Ajax
Google Chrome All versions · Desktop & Mobile
Full support
Mozilla Firefox All versions · Desktop & Mobile
Full support
Apple Safari All versions · macOS & iOS
Full support
Microsoft Edge All versions · Chromium & Legacy
Full support
Internet Explorer IE 6+ · Legacy environments
Full support
Opera All modern versions
Full support
ajaxStop Universal

Bottom line: Safe in any jQuery project using $.ajax(), $.get(), $.post(), or .load(). Prefer .on('ajaxStop') over deprecated .ajaxStop().

Conclusion

The jQuery ajaxStop event is the global “last request finished” hook — it runs once when the final qualifying Ajax call completes and no others are active. Bind handlers on document with .on("ajaxStop", fn), pair with ajaxStart for loading UI, and remember the handler receives no jqXHR or settings.

Use ajaxComplete when you need per-request details after each call finishes. Use global: false to opt out. Continue with the .ajaxStop() method tutorial for the deprecated shorthand API you will see in legacy code.

💡 Best Practices

✅ Do

  • Bind on $(document).on("ajaxStop", handler)
  • Pair with ajaxStart to show loading UI when activity begins
  • Use for page-wide spinners — not per-request logging
  • Use global: false for silent background or third-party requests
  • Remove handlers with $(document).off("ajaxStop") on SPA teardown

❌ Don’t

  • Attach global handlers to window — use document since jQuery 1.9
  • Use deprecated .ajaxStop(handler) in new code
  • Expect jqXHR or settings in the handler — use ajaxComplete instead
  • Hide loading UI on ajaxComplete during parallel batches — use ajaxStop
  • Assume ajaxStop fires for every request — it fires once per batch

Key Takeaways

Knowledge Unlocked

Six things to remember about ajaxStop

Last request, global batch, pair ajaxStart.

6
Core concepts
02

Last only

Per batch

Timing
start 03

ajaxStart

Show UI

Pair
done 04

ajaxComplete

Per request

Details
off 05

global:false

Opt out

Private
.on 06

.on()

Not .ajaxStop()

Modern

❓ Frequently Asked Questions

ajaxStop is a global Ajax event (AjaxEvent) that fires when all qualifying jQuery Ajax requests have completed — when no global Ajax requests remain active. Bind handlers with $(document).on('ajaxStop', handler) since version 1.7.
Since jQuery 1.9, all global Ajax event handlers — including ajaxStop — must be bound to document, not window or other elements. Use $(document).on('ajaxStop', fn) and $(document).off('ajaxStop', fn) to remove them.
ajaxComplete fires after every individual qualifying request finishes — success or error — with jqXHR and settings. ajaxStop fires once when the last active global request completes and the active count returns to zero. For three parallel calls: ajaxComplete runs three times; ajaxStop runs once.
No. ajaxStop fires only when no global Ajax requests remain in progress. If you launch three parallel $.ajax() calls, ajaxStop runs once after the last one finishes. Pair it with ajaxStart, which fires once when the first request begins.
When $.ajax() or $.ajaxSetup() sets global: false, that request opts out of all global Ajax events. ajaxStop will not fire for it, and it does not count toward active global requests for ajaxStart/ajaxStop pairing.
The handler is a simple function with no jQuery-specific arguments — function() { ... }. Unlike ajaxComplete or ajaxSend, you do not receive jqXHR or settings. Use ajaxComplete when you need per-request details.
Did you know?

jQuery maintains an internal counter of active global Ajax requests. ajaxStop fires when that counter returns to 0 — after the last qualifying request completes or is cancelled via beforeSend returning false. That is why three parallel $.get() calls produce one spinner hide — not three. The deprecated .ajaxStop(fn) method is equivalent to .on("ajaxStop", fn) on document.

Next: .ajaxStop() Method

Learn the deprecated shorthand for binding global ajaxStop handlers in legacy jQuery code.

.ajaxStop() method tutorial →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

6 people found this page helpful