- Llambduh
- Posts
- JSONP: Why the Modern Web Removed the " P a d d i n g "
JSONP: Why the Modern Web Removed the " P a d d i n g "
Trading Callbacks for Headers: How CORS Replaced the Web's Most Famous Workaround

Introduction: The Single Threaded Paradox
Cast your mind back to the mid 2000s. The "Web 2.0" era was in full swing, and developers were eager to build dynamic, interconnected applications. The vision was clear: seamlessly pull data from a weather service, a mapping application, and a social network, and stitch it all together on a single webpage. But there was a massive, frustrating roadblock standing in the way: the Same Origin Policy.
Designed as a fundamental security mechanism, the Same Origin Policy was the browser's strict bouncer. It explicitly forbade your webpage's JavaScript (via XMLHttpRequest) from reading data fetched from outside your site's originating domain, URI scheme, or port number. If your site lived at mysite.com, the browser outright refused to let your code read a pure JSON response from http://api.weather.com. It was a necessary walled garden to protect users, but it made building rich, cross domain web applications a logistical nightmare.
Enter one of the most famous and clever workarounds in internet history. In 2005, a developer named Bob Ippolito proposed a rogue but brilliant technique called JSONP (JSON with Padding). JSONP wasn't a shiny new web standard drafted by a committee; it was a cunning hack that weaponized a deliberate blind spot in the browser's security model. For years, this "padding" would serve as the duct tape holding the interconnected web together, allowing developers to finally smash through the walled garden.
The Workaround: How JSONP Tricked the Browser
To understand JSONP, you have to understand the specific loophole it exploited. While the browser strictly blocked background data requests to foreign servers, it had one notable exception: the HTML script element. By design, a script tag was perfectly allowed to retrieve and execute code from any domain. If it could not, loading external libraries or widgets from other servers would be completely impossible.
But developers faced a major dilemma. If a foreign service replied with pure JSON data, simply passing that URL into the src attribute of a script tag ended in disaster. The browser would download the JSON file, attempt to evaluate the raw data as an executable block of code, and immediately throw a syntax error. Even if the browser somehow recognized the text as a JavaScript object literal, the data remained completely inaccessible because it lacked a variable assignment.
This is exactly where the "Padding" in JSONP comes in. The client and the server strike a clever bargain. The client appends a URL encoded query argument to the request, conventionally named jsonp or callback, specifying a function name like parseResponse. The server receives this request, generates the JSON payload, and then wraps or "pads" that pure data inside parentheses while prepending the requested function name.
Instead of returning raw JSON, the server returns a fully executable JavaScript document that looks like this:
parseResponse({"Name": "Foo", "Id": 1234});When this new script loads, the browser evaluates it and seamlessly executes the parseResponse function already defined in the client environment, passing the precious data inside as an argument. To make this feel like a true background data fetch, developers relied on a technique called script element injection. Using helper frameworks like jQuery, the code would dynamically create a brand new script element, inject it into the HTML DOM, fetch the padded data, and execute the callback all without ever reloading the page. It was an elegant illusion that completely bypassed the Same Origin Policy.
The Dark Side: Why JSONP Was a Security Nightmare
While JSONP solved a massive problem, it essentially required developers to leave their website's front door wide open. The fatal flaw of the technique was its core mechanism: it only functioned by giving a remote server explicit permission to execute arbitrary code directly inside the user's browser. If that foreign server was compromised and injected malicious JavaScript into the response, the original web page was entirely at its mercy. This blind trust bypassed the Same Origin Policy in the worst way possible, opening a Pandora box of security vulnerabilities.
One of the most glaring issues was Cross Site Request Forgery, often abbreviated as CSRF or XSRF. Because the HTML script element completely ignores origin restrictions, a malicious website could easily request JSON data belonging to another site. If a user was currently logged into a secure service in another tab, a malicious page could trigger a JSONP request, execute the callback in its own context, and silently siphon away passwords or sensitive user data.
The sheer danger of JSONP culminated in the infamous 2014 Rosetta Flash exploit. Security researchers discovered a wild vulnerability where attackers could craft a malicious ActionScript payload compiled into a Flash SWF file using entirely alphanumeric characters. By passing this cleverly disguised file as the callback parameter of a JSONP call, attackers tricked Adobe Flash Player into believing the applet originated from the vulnerable server. This allowed them to steal sensitive cross origin data with ease.
High profile tech giants like Google, YouTube, Twitter, and LinkedIn were all vulnerable to this exploit until July 2014. Before Adobe could finalize a patch, panicked websites scrambled to protect themselves by prepending an empty JavaScript comment (/**/) or a simple newline to the beginning of their JSONP responses, a desperate measure to intentionally break the Flash file format and stop the bleeding.
Enter CORS: Trading Callbacks for Headers
The turning point for web security arrived in 2009 with the introduction of Cross Origin Resource Sharing, universally known as CORS. Unlike the clever but dangerous script injection of JSONP, CORS provided a legitimate, standardized mechanism for browsers and servers to communicate across different domains. Instead of wrapping data in executable JavaScript and crossing your fingers, CORS shifted the responsibility of access control entirely to HTTP headers.
When a modern web application makes a cross origin request, the browser checks the server response for specific CORS headers. If the server explicitly grants permission to the requesting domain, the browser securely hands over the pure JSON data. There are no executable payloads, no rogue script tags, and no risk of inadvertently running malicious code. The data remains strictly data, evaluated purely as an object literal rather than an invoked function.
The transition was not entirely overnight. As the security flaws of JSONP became impossible to ignore, there was actually a concerted effort around 2011 to define a safer, strict subset of JSONP. The idea was to enforce a specific MIME type for padded JSON, allowing browsers to throw an error or ignore the payload entirely if the response contained anything other than perfectly safe data. However, this approach was ultimately abandoned. The web development industry collectively realized that patching a fundamentally flawed workaround was pointless when CORS offered a vastly superior, deeply integrated, and built in solution.
Conclusion: Rest in Peace, JSONP
Looking back, it is easy to criticize JSONP for its glaring security flaws and messy implementation. However, we must acknowledge its legacy as a crucial, necessary stepping stone in the evolution of the internet. Before standards bodies could catch up to the ambitious demands of developers, JSONP was the clever workaround that allowed modern web APIs to flourish. It enabled the very first cross domain mashups, interactive widgets, and interconnected social feeds that defined the early Web 2.0 experience.
Today, JSONP is largely a relic of the past, relegated to the history books of web development. While it remains a fascinating study in how developers can creatively bypass strict browser limitations, its retirement is a massive win for user safety. As we build the highly secure, interconnected applications of tomorrow, we can all be immensely thankful that the modern web relies on verified HTTP headers rather than trusting arbitrary, executable padding.
