jQuery ajaxTransport() Method

Intermediate
9 min read
Updated: Oct 2026
5 examples
Live preview

What Is ajaxTransport()?

jQuery.ajaxTransport(dataType, handler) (since 1.5) registers a factory that can return a transport object with send and abort. jQuery uses that object to transmit the request for the given dataType.

Remember
$.ajaxTransport(dataType, function (options, originalOptions, jqXHR) {
  if (/* can handle */) {
    return {
      send: function (headers, completeCallback) { /* transmit */ },
      abort: function () { /* cancel */ }
    };
  }
  // return undefined → jQuery tries another transport
});

// Pipeline: ajaxSetup → ajaxPrefilter → transport.send → completeCallback
NeedUse
Tweak options / abort early$.ajaxPrefilter()
Convert response formatsconverters in $.ajax() / setup
Custom transmission$.ajaxTransport() (last resort)
Normal JSON / HTML / script$.ajax() built-ins

How to Use ajaxTransport()

Register a factory for one dataType, return { send, abort } only when you can handle the request, then call completeCallback when done.

  1. Call $.ajaxTransport("yourType", factory) once at bootstrap.
  2. Inside the factory, inspect options (and optionally originalOptions, jqXHR).
  3. If you can handle it, return { send, abort }; otherwise return nothing.
  4. In send, transmit (or mock) data, then call completeCallback(status, statusText, responses).
  5. Put the response under a key that matches your dataType (for example { image: img }).
PieceRequired?Role
dataTypeYesWhich requests ask this factory first
factoryYesfunction(options, originalOptions, jqXHR)
sendYes (if returning)function(headers, completeCallback)
abortYes (if returning)Cancel in-flight work; ignore late callbacks

Pseudocode

Pseudocode
$.ajaxTransport(dataType, factory)

when $.ajax({ dataType }) runs:
    call factory(options, originalOptions, jqXHR)
    if factory returns undefined:
        try next transport (often XHR)
    else:
        call transport.send(headers, completeCallback)
        when finished:
            completeCallback(status, statusText, responses [, headers])
        if jqXHR.abort():
            call transport.abort()

Cheat Sheet

Keep these facts handy while reading or writing a custom transport.

TopicDetail
Register$.ajaxTransport("type", factory)
SincejQuery 1.5
Return{ send, abort } or undefined
completeCallback(status, statusText, responses [, headers])
responses keyMatch your dataType (e.g. { image: img })
optionsMerged settings for this request
originalOptionsCaller options before ajaxSettings merge
Prefer firstPrefilters + converters, then transport

Live Preview

A tiny demo transport answers demo:// URLs instantly — no network required.

Custom transport only — no HTTP. Works offline.

Result
Ready — pick an action and click Run.

jQuery Examples

Short, copy-ready snippets. Prefer built-in Ajax for normal APIs — these demos show the transport layer itself.

Example 1 — Factory Skeleton

Return a transport only when you can handle the request; otherwise fall through.

jQuery
$.ajaxTransport("demo", function (options) {
  if (options.type === "GET" && options.url.indexOf("demo://") === 0) {
    return {
      send: function (headers, completeCallback) {
        var payload = options.url.replace("demo://", "");
        completeCallback(200, "success", {
          demo: "Demo says: " + payload
        });
      },
      abort: function () {}
    };
  }
});

$("#run").on("click", function () {
  $.ajax({
    url: "demo://Hello transport",
    dataType: "demo"
  }).done(function (text) {
    $("#log").text(text);
  });
});
Try It Yourself

How It Works

  1. Register. The factory is tied to dataType: "demo".
  2. Gate. Only demo:// GET URLs return a transport.
  3. Respond. responses.demo matches the dataType key.
  4. Fall through. Non-matching calls return nothing so XHR can run.

Example 2 — Official Image Transport Pattern

Load images with new Image() instead of XHR when dataType: "image".

jQuery
$.ajaxTransport("image", function (s) {
  if (s.type === "GET" && s.async) {
    var image;
    return {
      send: function (_, callback) {
        image = new Image();
        function done(status) {
          if (!image) return;
          var statusText = status === 200 ? "success" : "error";
          var tmp = image;
          image = image.onerror = image.onload = null;
          callback(status, statusText, { image: tmp });
        }
        image.onload = function () { done(200); };
        image.onerror = function () { done(404); };
        image.src = s.url;
      },
      abort: function () {
        if (image) {
          image = image.onerror = image.onload = null;
        }
      }
    };
  }
});

$("#load").on("click", function () {
  $.ajax({
    url: "https://picsum.photos/200",
    dataType: "image"
  }).done(function (img) {
    $("#preview").empty().append(img);
  });
});
Try It Yourself

How It Works

  1. Gate. Only async GET requests use this transport.
  2. Load. Setting image.src starts the browser fetch.
  3. Complete. Success/error call callback with an image response key.
  4. Abort. Clearing handlers prevents a late callback after cancel.

Example 3 — Mock JSON Without HTTP

Return hard-coded JSON instantly for mockjson:// URLs — great for prototypes.

jQuery
$.ajaxTransport("mockjson", function (options) {
  if (options.url.indexOf("mockjson://") === 0) {
    return {
      send: function (headers, completeCallback) {
        var id = options.url.replace("mockjson://user/", "");
        var user = {
          id: parseInt(id, 10) || 1,
          name: "Mock User " + id,
          email: "user" + id + "@example.test"
        };
        completeCallback(200, "success", { mockjson: user });
      },
      abort: function () {}
    };
  }
});

$("#fetch").on("click", function () {
  $.ajax({
    url: "mockjson://user/42",
    dataType: "mockjson"
  }).done(function (user) {
    $("#out").text(user.name + " — " + user.email);
  });
});
Try It Yourself

How It Works

  1. Match. Only mockjson:// URLs return a transport.
  2. Build. send creates a fake user from the URL id.
  3. Key. responses.mockjson matches dataType: "mockjson".
  4. Done. .done() receives the object directly — no HTTP.

Example 4 — abort() Cancels a Delayed Transport

Prove that jqXHR.abort() calls your transport’s abort and blocks a late callback.

jQuery
$.ajaxTransport("slow", function (options) {
  if (options.url.indexOf("slow://") === 0) {
    var timer;
    return {
      send: function (headers, completeCallback) {
        timer = setTimeout(function () {
          timer = null;
          completeCallback(200, "success", { slow: "Finished late" });
        }, 2000);
      },
      abort: function () {
        if (timer) {
          clearTimeout(timer);
          timer = null;
        }
      }
    };
  }
});

var req;
$("#start").on("click", function () {
  $("#log").text("Started…");
  req = $.ajax({ url: "slow://demo", dataType: "slow" })
    .done(function (msg) { $("#log").text(msg); })
    .fail(function () { $("#log").text("Aborted or failed."); });
});

$("#cancel").on("click", function () {
  if (req) req.abort();
});
Try It Yourself

How It Works

  1. Delay. send schedules a timeout instead of HTTP.
  2. Abort. jqXHR.abort() calls your abort method.
  3. Clear. Clearing the timer prevents completeCallback.
  4. Fail. An aborted request rejects the jqXHR promise.

Example 5 — When Not to Use a Transport

Ordinary JSON APIs already work — skip custom transports for standard HTTP.

jQuery
// No ajaxTransport needed for normal JSON
$("#go").on("click", function () {
  $.getJSON("https://jsonplaceholder.typicode.com/users/1")
    .done(function (user) {
      $("#out").text(user.name);
    })
    .fail(function () {
      $("#out").text("Request failed — check network.");
    });
});

// Reach for ajaxTransport only when:
// - custom protocol / non-HTTP source
// - Image / binary path XHR cannot handle well
// - in-memory mocks you intentionally own
Try It Yourself

How It Works

  1. Built-in. jQuery already transports JSON over XHR.
  2. Shorthand. $.getJSON() sets the right dataType for you.
  3. Simpler. Prefer prefilters for headers/url tweaks.
  4. Rule. Add a transport only when nothing else can transmit the data.

Edge Cases & Pitfalls

Check these before shipping a custom transport.

factory

Always return a fresh object

Never reuse one shared transport across requests — concurrent calls need isolated state.

responses

Match the dataType key

Put the payload under responses[yourDataType] so .done() receives it reliably.

abort

Ignore late callbacks after abort

Clear timers/handlers in abort so a cancelled request cannot call completeCallback later.

scope

Do not replace XHR for normal APIs

JSON/HTML/script already have built-in transports. Prefer prefilters for option tweaks.

Browser Support

jQuery.ajaxTransport() has been part of jQuery since 1.5. It works wherever your loaded jQuery Ajax module runs.

✓ Stable · jQuery 1.5+

jQuery.ajaxTransport()

Supported across modern jQuery 1.x/2.x/3.x builds that include Ajax. Prefer current jQuery 3.x. Note: the single-object completeCallback form is newer (3.8+ / 4.1); positional args work broadly.

100% jQuery Ajax API
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
$.ajaxTransport() Universal

Bottom line: Available wherever jQuery Ajax runs. Keep transports rare — most apps never need a custom one.

Performance Notes

ApproachCostBest for
Built-in XHR / JSONCheapNormal HTTP APIs
$.ajaxPrefilter()CheapOption tweaks, early abort
Custom transportMore code · careful abortNon-HTTP / special dataTypes only

Transport registration itself is cheap. Complexity comes from owning send/abort correctly — especially under concurrent requests.

Key Takeaways

  • Role: lowest-level hook that actually transmits Ajax data.
  • API: factory returns { send, abort } or nothing.
  • Complete: call completeCallback(status, statusText, responses).
  • Prefer first: prefilters and converters before writing a transport.

One line: $.ajaxTransport() lets you own send/abort for a dataType — powerful, rare, and usually unnecessary.

Frequently Asked Questions

jQuery.ajaxTransport(dataType, handler) registers a factory that jQuery calls when selecting how to transmit a request for that dataType. If the factory can handle the call, it returns an object with send and abort. Otherwise it returns undefined and jQuery tries another transport. This is the lowest-level Ajax extension point.
send(headers, completeCallback) starts transmission and must eventually call completeCallback when finished. abort() cancels an in-flight request — clear timers, detach Image handlers, or ignore late callbacks so completeCallback does not fire after cancel.
On jQuery 3.7 (common in tutorials), use the positional form: completeCallback(status, statusText, responses, headers). status is like 200 or 404; statusText is "success" or "error"; responses maps dataType keys to values (for example { image: imgElement }); headers is an optional response-header string. Newer jQuery versions also accept a single params object.
ajaxPrefilter runs earlier to tweak options (url, headers, cache) or abort. ajaxTransport replaces how bytes are sent and received for matching dataTypes. Prefer prefilters for option changes; use transports only when prefilters and converters are not enough.
As a last resort: custom protocols, Image-based loads, in-memory mocks, or non-HTTP sources. For ordinary JSON, HTML, or script requests, built-in $.ajax() transports already work — do not register a custom transport.
Each request needs its own transport instance with isolated state (timers, Image nodes, sockets). Registering one shared object would let concurrent requests clobber each other. The factory returns a fresh { send, abort } per matching request.

Next: jQuery.get() Method

Learn the everyday GET shorthand that uses jQuery’s built-in transports.

jQuery.get() 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