Question
What Is JSONP in JavaScript? Why It Was Created and How It Works
Question
I understand JSON as a data format, but I do not understand JSONP.
One definition says:
JSONP or "JSON with padding" is a JSON extension wherein a prefix is specified as an input argument of the call itself.
That is confusing to me because JSON is just a data format. There is no obvious "call" involved.
Another explanation says:
JSONP is script tag injection, passing the response from the server into a user-specified function.
I partly understand that, but I still do not see the full picture.
So what exactly is JSONP? Why was it created, what problem was it trying to solve, and why would someone use it?
For example, what is happening in a pattern like this?
function handleData(data) {
console.log(data);
}
const script = document.createElement('script');
script.src = 'https://example.com/data?callback=handleData';
document.body.appendChild(script);
Short Answer
By the end of this page, you will understand that JSONP is not a new data format, but a technique for loading data by wrapping JSON inside a JavaScript function call. It was created to work around older browser same-origin restrictions that blocked normal AJAX requests to other domains. You will learn how JSONP works, why it existed, its limitations, its security risks, and why modern applications usually use CORS instead.
Concept
JSONP stands for JSON with Padding.
The most important idea is this:
- JSON is plain data.
- JSONP is JavaScript code that calls a function and passes JSON data into it.
A normal JSON response looks like this:
{"name":"Alice","age":30}
A JSONP response looks like this:
handleData({"name":"Alice","age":30});
The handleData(...) part is the padding. The JSON data is wrapped in a function call.
Why JSONP was created
Older browsers enforced the same-origin policy for AJAX requests. That meant JavaScript on one website could not easily fetch data from another domain using XMLHttpRequest.
For example:
- A page on
https://myapp.comcould not make a normal AJAX request tohttps://api.example.com.
However, browsers did allow loading JavaScript files from other domains using a <script> tag:
<script src="https://api.example.com/file.js"></script>
This was allowed because websites often needed external scripts.
Developers realized they could use that permission to fetch data disguised as JavaScript.
Instead of returning raw JSON, the server returned JavaScript that called a function already defined on the page.
Example:
showUser({"id":1,"name":"Alice"});
When the browser loaded that script, it executed immediately and passed the data into showUser.
That workaround is JSONP.
What problem JSONP solved
JSONP solved this old problem:
- "I need data from another domain, but the browser blocks my AJAX request."
JSONP let developers retrieve data across domains without server-side proxies and before CORS became standard.
Why the word "call" is used
The confusing definition mentions a "call" because JSONP is based on a function call.
The browser requests a URL like this:
https://example.com/data?callback=handleData
The server reads the callback=handleData part and sends back:
handleData({"message":"Hello"});
That response is JavaScript code. When loaded through a <script> tag, the browser executes it.
So the "call" is the server-generated function call in the response.
Why JSONP matters historically
JSONP was very important before CORS.
It helped developers:
- load public API data from another domain
- build mashups using multiple services
- avoid building their own server-side relay just to fetch external data
Today, JSONP is mostly a legacy technique because CORS is safer and more flexible.
Mental Model
Imagine your web page is a house.
- JSON is like a sealed package left at the door. It contains data.
- AJAX is like sending someone through the front gate to pick up the package.
- The same-origin policy is a guard that says, "You cannot fetch packages from that other neighborhood."
But there is one exception:
- The guard allows newspapers from other neighborhoods to be delivered through the mail slot.
- A
<script>tag is that mail slot.
So instead of sending just a package of data, the other server sends a newspaper article that says:
handleData({"name":"Alice"});
Your page has already prepared a function named handleData, so when the script arrives, the browser reads it out loud and your function receives the data.
That is JSONP: using the browser's ability to load external scripts as a way to receive cross-domain data.
Syntax and Examples
Core pattern
Client-side code:
function handleData(data) {
console.log('Received:', data);
}
const script = document.createElement('script');
script.src = 'https://api.example.com/user?callback=handleData';
document.body.appendChild(script);
Possible server response:
handleData({"id":1,"name":"Alice"});
What each part does
- The page defines a global function such as
handleData. - The page creates a
<script>element. - The
srcpoints to another domain. - The URL includes a callback name.
- The server returns JavaScript that calls that function.
- The browser loads and executes that script.
Beginner-friendly example
Suppose you want weather data from another domain.
Page code
function showWeather(data) {
console.log(`City: ${data.city}`);
console.log(`Temperature: ${data.temperature}`);
}
const script = document.createElement('script');
script.src = 'https://weather.example.com/current?callback=showWeather';
document.body.appendChild(script);
Server response
showWeather({"city":"London","temperature":18});
Result
When the script loads, the browser executes:
showWeather({"city":"London","temperature":18});
So your showWeather function receives the data object.
Why this is not plain JSON
This is JSON:
{"city":"London","temperature":18}
This is JSONP:
showWeather({"city":"London","temperature":18});
JSONP is executable JavaScript, not just data.
Step by Step Execution
Consider this code:
function handleData(data) {
console.log('Name:', data.name);
}
const script = document.createElement('script');
script.src = 'https://example.com/user?callback=handleData';
document.body.appendChild(script);
Assume the server responds with:
handleData({"name":"Alice"});
Step-by-step
1. Define the callback function
function handleData(data) {
console.log('Name:', data.name);
}
The page creates a function named handleData. This function will receive data later.
2. Create a script element
const script = document.createElement('script');
This creates a new <script> tag in memory.
3. Set the source URL
script.src = 'https://example.com/user?callback=handleData';
The browser is told to load a script from another domain.
The URL includes callback=handleData, which tells the server which function name to use.
4. Add the script to the page
document.body.appendChild(script);
As soon as the script is added to the document, the browser requests the URL.
5. Server builds the response
The server sees callback=handleData and returns:
handleData({"name":"Alice"});
6. Browser executes the script
Because it came through a <script> tag, the browser treats the response as JavaScript code.
7. Your function runs
handleData({"name":"Alice"});
This calls your function with the object.
8. Output appears
Name: Alice
Key observation
The browser never parsed a JSON response from AJAX here. It simply loaded and executed JavaScript from another server.
Real World Use Cases
Historical use cases
JSONP was commonly used for:
- Public APIs that needed to support browser access from any site
- Widgets embedded on third-party websites
- Mashups that combined data from several services on one page
- Search suggestions and autocomplete from external services
- Analytics or ad scripts that returned dynamic data
Example scenarios
1. Public API consumption
A news site might fetch headlines from another domain using JSONP.
2. Embeddable widgets
A stock ticker widget embedded on many websites could request live data from the provider's domain.
3. Third-party integrations
A page could show social media counts or public profile information from another service.
Where it is less suitable
JSONP was never ideal for:
- private data
- authenticated requests
- non-GET operations
- reliable error handling
That is one reason modern apps prefer fetch with CORS.
Real Codebase Usage
In real projects, JSONP usually appeared as a fallback or as a feature for older APIs.
Common patterns
1. Callback parameter convention
Servers often accepted query parameters like:
callback=myFunctionjsonp=myFunctioncb=myFunction
The backend inserted that function name into the response.
2. Dynamically generated callback names
To avoid naming collisions, developers often generated unique global functions:
const callbackName = 'jsonpCallback_' + Date.now();
window[callbackName] = function (data) {
console.log(data);
delete window[callbackName];
};
3. Cleanup after execution
After the callback ran, code often removed:
- the global callback function
- the injected
<script>element
This prevented memory leaks and duplicate calls.
4. Guard clauses
Developers often checked that the response had expected fields before using it:
window[callbackName] = function (data) {
if (!data || !data.name) {
console.error('Invalid response');
return;
}
console.log(data.name);
};
5. Timeout handling
Because JSONP has weak error reporting, code often used timeouts:
const timeoutId = setTimeout(() => {
console.error('Request timed out');
}, 5000);
Then the callback cleared the timeout when data arrived.
Important limitation in real code
JSONP only works when the server explicitly supports it. A client cannot force an ordinary JSON endpoint to behave like JSONP.
Common Mistakes
1. Thinking JSONP is a data format
JSONP is not a replacement for JSON.
- JSON = data
- JSONP = JavaScript function call containing data
Broken assumption:
// Wrong idea: treating JSONP as plain JSON
const data = '{"name":"Alice"}';
Actual JSONP response:
handleData({"name":"Alice"});
2. Forgetting that the callback must exist globally
Because the response executes as script, the callback usually needs to be accessible on window.
Broken example:
(function () {
function handleData(data) {
console.log(data);
}
})();
If the server calls handleData(...), it may fail because handleData is not global.
Safer version:
window.handleData = function (data) {
console.log(data);
};
3. Assuming JSONP supports POST, PUT, or DELETE
JSONP works through a <script> URL request, so it is effectively limited to GET.
4. Ignoring security risks
A JSONP response is executable JavaScript from another domain.
That means you are not just accepting data — you are running code.
If the server is compromised or untrusted, that is dangerous.
5. Expecting good error handling
With fetch, you can inspect status codes more clearly. With JSONP, error handling is awkward and inconsistent.
6. Not cleaning up callbacks
If you create many JSONP requests and never remove the callback functions or script tags, your page can become messy.
7. Using JSONP when CORS is available
Modern APIs should usually use:
fetch('https://api.example.com/data')
with proper CORS headers on the server, instead of JSONP.
Comparisons
JSON vs JSONP
| Feature | JSON | JSONP |
|---|---|---|
| Type | Data format | JavaScript technique |
| Example | {"name":"Alice"} | handleData({"name":"Alice"}); |
| Executable | No | Yes |
| Cross-domain workaround | No | Yes, historically |
| Security risk | Lower | Higher, because it executes script |
JSONP vs AJAX with CORS
| Feature | JSONP | AJAX/fetch with CORS |
|---|---|---|
| Transport style | <script> tag | XMLHttpRequest or fetch |
| Supported methods | Mostly GET only | GET, POST, PUT, DELETE, etc. |
| Response type | JavaScript code | Data such as JSON |
| Error handling | Limited | Better |
| Security model | Executes third-party script | Controlled by CORS headers |
| Modern usage | Legacy | Standard |
JSONP vs server-side proxy
| Approach | How it works | When used |
|---|---|---|
| JSONP | Browser loads cross-domain script | Legacy public endpoints |
| Server-side proxy | Your server fetches remote data and forwards it | When you need control, auth, or safer integration |
When to choose what
- Use JSON for data representation.
- Use CORS for modern cross-origin browser requests.
- Use JSONP only when working with an old API that already supports it.
Cheat Sheet
Quick definition
- JSON: plain data format
- JSONP: JavaScript function call containing JSON data
- Purpose: old workaround for cross-domain browser restrictions
JSON example
{"name":"Alice"}
JSONP example
handleData({"name":"Alice"});
Basic flow
- Define a global callback function
- Create a
<script>tag - Set
srcto a URL with a callback parameter - Server returns JavaScript that calls your function
- Browser executes it
Typical client code
window.handleData = function (data) {
console.log(data);
};
const script = document.createElement('script');
script.src = 'https://example.com/api?callback=handleData';
document.body.appendChild(script);
Typical server response
handleData({"ok":true});
Key rules
- JSONP is not plain JSON
- JSONP requires server support
- JSONP usually works only with GET
- JSONP runs remote JavaScript
- JSONP is mostly replaced by CORS
Main drawbacks
- security risk
- poor error handling
- no clean support for most HTTP methods
- requires global callback naming
Modern alternative
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => console.log(data));
Use this with proper CORS headers on the server.
FAQ
Is JSONP the same as JSON?
No. JSON is a data format. JSONP is a technique where JSON data is wrapped inside a JavaScript function call.
Why was JSONP needed?
It was used to bypass old browser same-origin restrictions that blocked cross-domain AJAX requests.
Does JSONP still matter today?
Mostly for legacy systems. Modern applications usually use fetch or XMLHttpRequest with CORS.
Is JSONP safe?
It is less safe than plain JSON because it executes JavaScript from another domain. Only use it with trusted sources.
Can JSONP send POST requests?
No, not in the normal way. JSONP works through a <script> request, which is effectively GET-only.
Can any API be used with JSONP?
No. The server must explicitly support JSONP and return a callback-wrapped response.
What does "padding" mean in JSONP?
It means the JSON data is padded or wrapped with extra text: a function name and parentheses.
What replaced JSONP?
CORS became the standard solution for cross-origin browser requests.
Mini Project
Description
Build a small JSONP loader utility to understand how cross-domain script-based data loading works. This project demonstrates the full JSONP pattern: creating a callback, injecting a script tag, receiving data, handling timeouts, and cleaning up after the request.
Goal
Create a reusable jsonpRequest function that loads JSONP data from a URL and resolves it in a callback-based style.
Requirements
- Create a function that accepts a URL and a callback parameter name.
- Generate a unique global callback function name for each request.
- Inject a
<script>tag with the callback name added to the URL. - Call a success handler when data arrives.
- Clean up the script element and callback function after completion.
- Add timeout handling for requests that never respond.
Keep learning
Related questions
Abort Ajax Requests with jQuery jqXHR.abort()
Learn how to cancel an in-progress jQuery Ajax request with jqXHR.abort(), handle abort status safely, and avoid stale UI updates.
Access the Correct this Inside a JavaScript Callback
Learn why JavaScript this changes in callbacks and how to preserve an object context using bind, arrow functions, and event handler patterns.
Add Key-Value Pairs to JavaScript Objects
Learn how to add key-value pairs to JavaScript objects with dot and bracket notation, dynamic keys, examples, and common mistakes.