Himanshu SharmaSoftware engineer
Let’s talk

jQuery · Lesson 35 of 45

The $.ajax() method and its options

Use jQuery $.ajax() with url, method, data, dataType, headers and timeout options, and handle results with .done(), .fail() and .always() on the jqXHR object.

13 minAjaxUpdated 23 October 2026

By the end of this lessonWrite any HTTP request with $.ajax(), choose the right options, and handle success, failure and completion separately.

One method behind them all

$.get(), $.getJSON() and $.post() are shortcuts. They all call $.ajax(), which takes one object of options and can make any HTTP request:

html
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  $.ajax({
    url: "https://jsonplaceholder.typicode.com/users/2",
    method: "GET",
    dataType: "json"
  })
    .done(function (user, textStatus, jqXHR) {
      console.log("done:", user.name, "|", textStatus, "|", jqXHR.status);
    })
    .fail(function (jqXHR, textStatus, errorThrown) {
      console.log("fail:", jqXHR.status, textStatus, errorThrown);
    })
    .always(function () {
      console.log("always: the request has finished");
    });
</script>
result
done: Ervin Howell | success | 200
always: the request has finished

The jqXHR object

$.ajax() returns a jqXHR object straight away, before the response arrives. You attach handlers to it:

  • .done(fn) runs on success with (data, textStatus, jqXHR).
  • .fail(fn) runs on failure with (jqXHR, textStatus, errorThrown).
  • .always(fn) runs after either, which makes it the right place to hide a spinner or re-enable a button.
  • .then(success, failure) works too, and jqXHR can be used with await (Deferreds lesson).

Older code passes success:, error: and complete: functions inside the options object. They do the same job; the chained style is easier to read and lets you add handlers later, for example in a different function that receives the jqXHR.

The most useful options

Option Meaning
url where to send the request
method "GET" (default), "POST", "PUT", "PATCH", "DELETE" (type is the old name)
data values to send: an object, a string, or (with processData: false) FormData
dataType what you expect back: "json", "html", "text", "script"
contentType the format of what you send, e.g. "application/json"
headers extra request headers, such as an auth or CSRF token
timeout give up after this many milliseconds
cache false adds a timestamp parameter so browsers do not reuse an old GET response

Reading response details

The jqXHR object also exposes the HTTP status and headers:

html
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  $.ajax({ url: "https://jsonplaceholder.typicode.com/posts", data: { userId: 1 } })
    .done(function (posts, status, xhr) {
      console.log("status:", xhr.status);
      console.log("content type:", xhr.getResponseHeader("Content-Type"));
      console.log("posts:", posts.length, "| parsed automatically:", Array.isArray(posts));
    });
</script>
result
status: 200
content type: application/json; charset=utf-8
posts: 10 | parsed automatically: true

Without dataType, jQuery parses the response according to its Content-Type; this API sends application/json, so posts arrived as an array.

Handling a failure

The server may answer with an error status. With $.ajax(), any status outside 200 to 299 (and 304) goes to .fail():

html
<p id="msg"></p>

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  $.ajax({ url: "https://jsonplaceholder.typicode.com/posts/99999", dataType: "json" })
    .done(post => console.log("found", post.id))
    .fail(function (xhr, textStatus) {
      $("#msg").text(xhr.status === 404 ? "That post does not exist." : "Something went wrong.");
      console.log("failed with", xhr.status, "|", textStatus);
    });
</script>
result
failed with 404 | error

The next lessons cover sending data and handling every kind of failure, including timeouts and lost connections.

Defaults for every request

$.ajaxSetup(options) sets defaults used by every later request. The most common real use is sending a CSRF token with every request in frameworks like Laravel, which put it in a meta tag:

javascript
$.ajaxSetup({
  headers: { "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content") }
});

Use $.ajaxSetup() only for settings that truly apply everywhere. Defaults that change the behaviour of all requests, such as a global dataType or timeout, surprise anyone reading a single $.ajax() call (and break plugins that make their own requests). Prefer a small wrapper function of your own:

javascript
function api(path, options) {
  return $.ajax($.extend({ url: "/api" + path, dataType: "json", timeout: 10000 }, options));
}

api("/products").done(render);

Global Ajax events

jQuery fires events on document for every request: ajaxStart (the first request begins), ajaxStop (all requests have finished), plus ajaxSend, ajaxSuccess, ajaxError and ajaxComplete. A page-wide "loading" indicator can use them:

javascript
$(document)
  .on("ajaxStart", () => $("#busy").show())
  .on("ajaxStop", () => $("#busy").hide());

Pass global: false in a request's options to keep it out of these events.

Common mistakes

  • Expecting $.ajax() to return the data. It returns jqXHR; the data arrives in .done().
  • Using dataType to send JSON. It only describes the response.
  • Forgetting .fail(), so errors leave the page stuck on "Loading...".
  • Putting clean-up only in .done(), so a failed request never re-enables the button. Use .always().

Exercise

Use $.ajax() to load https://jsonplaceholder.typicode.com/todos/5. On success, log done: with the to-do's title; on failure, log failed: with the status; and in .always(), log finished.

Show one possible answer
html
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  $.ajax({ url: "https://jsonplaceholder.typicode.com/todos/5", dataType: "json" })
    .done(task => console.log("done:", task.title))
    .fail(xhr => console.log("failed:", xhr.status))
    .always(() => console.log("finished"));
</script>
result
done: laboriosam mollitia et enim quasi adipisci quia provident illum
finished

Key points

  • $.ajax({ url, method, data, dataType, headers, timeout }) is the full-featured request method; the shortcuts all call it.
  • It returns a jqXHR object; attach .done() for success, .fail() for errors and .always() for code that runs either way.
  • dataType says what you expect back ("json", "html", "text"); method sets GET, POST, PUT, PATCH or DELETE.
  • $.ajaxSetup() sets defaults for every request, such as a CSRF header, but use it sparingly.

Check yourself

1. What does $.ajax() return?
2. Which handler runs whether the request succeeds or fails?
3. Which option sets the HTTP method?
4. What does dataType: "json" do?