AJAX means talking to a server in the background, without reloading the page. A search box that shows suggestions as you type, a “Load more” button, a form that says “Thanks!” without leaving the page – all of these use AJAX. The jQuery AJAX methods were a big reason for its popularity, and you will meet them in a lot of existing code. The modern built-in alternative is fetch(), covered in Fetch and Async JavaScript.
How a jQuery AJAX request works
- Your script sends an HTTP request to a URL, for example
/api/products. - The page stays usable while the request travels – it is asynchronous.
- The server replies, usually with JSON: text that looks like JavaScript objects and arrays.
- jQuery parses the JSON and calls your success function with the data, or your error function if something went wrong.
- Your code updates the page with the new data.
The examples on this page run in a sandbox with no server of its own, so they load sample data from JSONPlaceholder, a free public test API that allows requests from any website. Its data is placeholder text, not real people.
The quick way: $.getJSON()
$.getJSON(url) sends a GET request and parses the JSON reply. It returns a jqXHR object, which works like a promise: .done() runs on success, .fail() on error, and .always() in both cases – the right place to hide a loading message.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Loading users with $.getJSON()</title>
<style>
body { font-family: system-ui, sans-serif; padding: 16px; line-height: 1.5; }
li { margin: 4px 0; }
.error { color: #b91c1c; }
</style>
</head>
<body>
<button id="load" type="button">Load users</button>
<p id="status" role="status">Click the button to load data.</p>
<ul id="users"></ul>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
const $status = $('#status');
const $list = $('#users');
const $btn = $('#load');
$btn.on('click', () => {
$btn.prop('disabled', true);
$status.removeClass('error').text('Loading…');
$list.empty();
$.getJSON('https://jsonplaceholder.typicode.com/users')
.done((users) => {
const items = users.map((user) =>
$('<li>').text(`${user.name} – ${user.address.city}`) // .text(): safe for any data
);
$list.append(items);
$status.text(`Loaded ${users.length} users.`);
})
.fail((jqXHR, textStatus) => {
$status.addClass('error').text(`Could not load users (${textStatus}). Please try again.`);
})
.always(() => {
$btn.prop('disabled', false);
});
});
</script>
</body>
</html>Notice the three states every AJAX feature needs: loading (a message and a disabled button so people do not click five times), success and error. Networks fail, especially on mobile data, so never skip the error message.
Full control with $.ajax()
$.getJSON(), $.get() and $.post() are jQuery AJAX shortcuts. Underneath they all call $.ajax(), which takes one settings object:
| Setting | Meaning |
|---|---|
url | Where to send the request |
method | 'GET' (default), 'POST', 'PUT', 'DELETE'… (older code uses type) |
data | Data to send – an object becomes name=value&… form data |
contentType | The format of the data you send, e.g. 'application/json' |
dataType | The format you expect back: 'json', 'text', 'html'… |
timeout | Give up after this many milliseconds |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Sending data with a POST request</title>
<style>
body { font-family: system-ui, sans-serif; padding: 16px; line-height: 1.5; }
label { display: block; margin-top: 8px; }
pre { background: #f3f4f6; padding: 8px; white-space: pre-wrap; }
</style>
</head>
<body>
<form id="review">
<label for="title">Review title</label>
<input id="title" name="title" type="text" value="Great filter coffee">
<label for="body">Your review</label>
<textarea id="body" name="body" rows="2">Strong, fresh and served hot.</textarea>
<p><button type="submit">Post review</button></p>
</form>
<p id="status" role="status"></p>
<pre id="reply"></pre>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
$('#review').on('submit', (event) => {
event.preventDefault();
$('#status').text('Sending…');
$.ajax({
url: 'https://jsonplaceholder.typicode.com/posts',
method: 'POST',
contentType: 'application/json',
data: JSON.stringify({
title: $('#title').val().trim(),
body: $('#body').val().trim(),
userId: 1
}),
dataType: 'json',
timeout: 8000
})
.done((saved) => {
$('#status').text(`Saved with id ${saved.id}.`);
$('#reply').text(JSON.stringify(saved, null, 2));
})
.fail((jqXHR, textStatus) => {
$('#status').text(`Sending failed: ${textStatus}`);
});
});
</script>
</body>
</html>Tip: JSONPlaceholder only pretends to save: it replies as a real API would, with a new id, but nothing is stored. With your own server, the same code would insert a row into the database.
Using async and await
Because the jqXHR object is “thenable”, you can await it inside an async function, just like fetch(). If the request fails, await throws – and the thrown value is the jqXHR object, so you can read err.status.
async function loadPosts() {
try {
const posts = await $.getJSON('https://jsonplaceholder.typicode.com/posts?userId=1');
$('#status').text(`${posts.length} posts`);
} catch (err) {
$('#status').text(`Error ${err.status}`);
}
}
// The same with fetch(): note that fetch does NOT reject on 404 or 500
async function loadPostsWithFetch() {
const response = await fetch('https://jsonplaceholder.typicode.com/posts?userId=1');
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const posts = await response.json();
document.getElementById('status').textContent = `${posts.length} posts`;
}Practising without any API
If you are offline, or want to test your rendering code with exact data, you can request a data: URL. The JSON is written inside the URL itself, so no network is needed, yet jQuery handles it like a normal response. This is only a learning trick – real data always comes from a server.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Loading JSON from a data: URL</title>
<style>
body { font-family: system-ui, sans-serif; padding: 16px; line-height: 1.5; }
</style>
</head>
<body>
<p id="status" role="status">Loading menu…</p>
<ul id="menu"></ul>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
const menu = [
{ dish: 'Ghee roast dosa', price: 120 },
{ dish: 'Kothu parotta', price: 150 },
{ dish: 'Rose milk', price: 60 }
];
const url = 'data:application/json,' + encodeURIComponent(JSON.stringify(menu));
$.getJSON(url)
.done((items) => {
$('#menu').append(items.map((item) => $('<li>').text(`${item.dish} – ₹${item.price}`)));
$('#status').text(`${items.length} dishes on today's menu.`);
})
.fail(() => $('#status').text('Could not read the menu.'));
</script>
</body>
</html>With a real server
On a real site you usually call your own back end, such as a PHP file that reads the database with PDO and prints JSON. Requests to the same domain just work. Requests to another domain only work if that server sends CORS headers allowing your site; otherwise the browser blocks the response and .fail() runs.
- Always validate and sanitise data on the server too – anyone can send requests without using your page.
- Show server data with
.text(), not.html(), unless you fully trust and control that HTML. - jQuery 4 no longer turns a JSON request into JSONP automatically, for security reasons. Use CORS; ask for JSONP only on purpose with
dataType: 'jsonp'. $('#box').load('part.html')loads an HTML fragment into an element. It needs a server and is handy in older sites.
