JS JSONP
In this page:
Why JSONP Exists
Before CORS, browsers strictly blocked JavaScript from making a cross-origin XMLHttpRequest to a different domain -- but a <script> tag has always been allowed to load a script from any domain, so JSONP exploits that loophole: the "response" is actually loaded as if it were a script file.
Note: Understand JSONP as a historical workaround for a limitation (no CORS) that no longer exists in modern browsers and APIs -- CORS is the correct modern solution for the same underlying problem.
Warning: JSONP predates the security-conscious CORS model, and its very technique (executing remote code) is exactly the kind of thing CORS was designed to prevent doing carelessly.
Example: Why JSONP Exists
<script src="https://api.example.com/data?callback=handleData"></script>
<script>
function handleData(data) { console.log(data); }
</script>
How JSONP Works
The client defines a global callback function and requests a URL that includes that function's name as a query parameter -- the server wraps its JSON data in a call to that exact function name, so when the returned "script" loads and executes, it automatically calls your function with the data as an argument.
Note: Make sure your callback function is defined and globally accessible before the JSONP script tag attempts to load, or the call will fail with a "function not defined" error.
Warning: The callback function name in the request and the function name the server wraps the data in must match exactly, or nothing happens when the script loads.
Example: How JSONP Works
function handleData(data) {
console.log("Received:", data);
}
// Server responds with: handleData({"name": "Sam"});
// which calls handleData automatically once the "script" loads
Dynamically Creating a JSONP Request
Rather than hardcoding a <script> tag in the HTML, JSONP requests are typically triggered dynamically -- creating a new <script> element with JavaScript, setting its src to the target URL, and appending it to the document, which starts the request immediately.
Note: Remove the dynamically created script tag after it finishes loading (in the callback, or via an onload handler) to keep the DOM clean if many JSONP requests will be made over time.
Warning: A dynamically created JSONP request has no built-in way to detect a failure the way fetch's .catch() does -- a failed or blocked script load can leave your callback simply never called, with no direct error signal.
Example: Dynamically Creating a JSONP Request
function handleData(data) { console.log(data); }
const script = document.createElement("script");
script.src = "https://api.example.com/data?callback=handleData";
document.body.appendChild(script);
JSONP's Limitations
JSONP only supports GET requests, since it relies on loading a URL as a script -- there is no equivalent for sending a POST body. It also offers no clean way to detect a failed request (no error callback is standard), and it executes the response as real, unrestricted JavaScript in your page.
Note: Never use JSONP for anything beyond a simple, read-only GET request, and only when the target API genuinely does not support CORS.
Warning: Because a JSONP response executes as arbitrary JavaScript in your page's context, only use it against APIs and domains you genuinely trust -- a malicious or compromised server could run harmful code through this channel.
Example: JSONP's Limitations
// JSONP limitations:
// - only supports GET (loading a URL as a script)
// - no built-in error callback if the request fails
// - executes the response as full, unrestricted JavaScript
console.log("Use CORS with fetch() instead when the API supports it.");
JSONP vs CORS: When to Use Which
For any API you control, or any modern third-party API, CORS is the correct, secure choice -- it lets the server explicitly declare which origins may access it, and works with the full range of HTTP methods and the safer fetch API. JSONP remains relevant only for old APIs that never added CORS support.
Note: Check first whether an API supports CORS before reaching for JSONP -- most modern public APIs do, making JSONP unnecessary.
Warning: Choosing JSONP for a new integration when CORS is available adds unnecessary security risk and GET-only limitations for no real benefit.
Example: JSONP vs CORS: When to Use Which
fetch("https://api.example.com/data").then(r => r.json()).then(data => console.log(data));
console.log("Prefer CORS/fetch whenever the server supports it.");
- Using JSONP for a new project today when the target API supports CORS -- JSONP has real security downsides and should only be used when CORS is genuinely unavailable.
- Forgetting that JSONP only supports GET requests, since it works by loading a script, and scripts cannot carry a POST body.
- Not recognizing that JSONP executes arbitrary code from the remote server directly in your page's context, which is a meaningful security consideration compared to a same-origin-protected JSON fetch.
- JSONP works by dynamically inserting a <script> tag whose src points to the remote API, sidestepping the same-origin restriction that blocks a plain cross-origin XMLHttpRequest.
- The remote server wraps its JSON data in a call to a callback function name the client specifies, which executes automatically once the script loads.
- JSONP only supports GET requests and executes the remote server's response as actual JavaScript, a real security consideration.
JSONP relies only on basic <script> tag loading, supported in every browser since the earliest days of the web; it predates and is now largely superseded by CORS.
Chapter Quiz — Complete all 26 topics to unlock
0/26 topics done
Complete these topics first:
- JS JSON
- JS Regular Expressions
- JS Fetch API
- JS LocalStorage and SessionStorage
- JS Cookies
- JS setTimeout and setInterval
- JS Event Loop
- JS Web Workers
- JS Service Workers
- JS AJAX
- JS AJAX Intro
- JS AJAX XMLHttp
- JS AJAX Request
- JS AJAX Response
- JS AJAX XML
- JS AJAX PHP
- JS AJAX Database
- JS JSONP
- JS RegExp Flags
- JS RegExp Classes
- JS RegExp Metachars
- JS RegExp Assertions
- JS RegExp Groups
- JS RegExp Quantifiers
- JS JSON HTML
- JS JSON vs XML