Of course! Let's break down JSONPCallback in Python. This is a crucial concept for understanding how web applications can securely communicate across different domains before the widespread adoption of CORS.

What is JSONP? (The "Why")
JSONP stands for JSON with Padding.
At its core, it's a technique used to get data from a server on a different domain than the one the web page was loaded from. This is a fundamental restriction enforced by the browser's Same-Origin Policy.
- The Problem: A webpage from
https://myapp.comcannot normally make a direct AJAX request tohttps://api.someotherdomain.com/data. The browser will block this for security reasons. - The JSONP Solution: Instead of a standard AJAX request, JSONP uses a
<script>tag. The browser does not apply the Same-Origin Policy to<script>tags, allowing them to load scripts from any domain. The server is configured to respond with executable JavaScript code (a function call) instead of just raw JSON.
How JSONP Works: The Step-by-Step Flow
-
The Request: Your webpage includes a
<script>tag whosesrcURL points to the API endpoint. Crucially, you add a special query parameter, usually namedcallback, with the name of a JavaScript function you've defined on your page.<!-- The function that will handle the data --> <script> function myDataHandler(data) { console.log("Received data:", data); // Do something with the data, like display it on the page } </script> <!-- The JSONP request --> <script src="https://api.someotherdomain.com/data?callback=myDataHandler"></script> -
The Server-Side Response: The server sees the
callback=myDataHandlerparameter. It doesn't just send back{"name": "John", "id": 123}. Instead, it "wraps" the JSON data in a function call, using the value of thecallbackparameter.
(图片来源网络,侵删)The server's response looks like this (it's valid JavaScript!):
myDataHandler({"name": "John", "id": 123}); -
The Execution: The browser downloads this response and executes it as JavaScript. Since
myDataHandleris a function that already exists on your page, this code calls your function and passes the JSON object as an argument. -
The Result: Your
myDataHandlerfunction now has the data and can process it. The communication is complete and secure because you only execute code from a domain you trust.
Implementing a JSONP Server in Python
The key to implementing JSONP is on the server. The server must inspect the request for a callback parameter and wrap its JSON response accordingly.

Here are two common ways to do this in Python.
Method 1: Using Flask (A Simple Example)
Flask is a lightweight web framework that makes this very easy.
Install Flask:
pip install Flask
Create the server (app.py):
This server will have one endpoint /api/data. It will check for a callback parameter.
from flask import Flask, jsonify, request
app = Flask(__name__)
# This is our standard JSON data
data = {
"users": [
{"id": 1, "name": "Alice", "email": "alice@example.com"},
{"id": 2, "name": "Bob", "email": "bob@example.com"}
]
}
@app.route('/api/data')
def get_data():
# Get the callback parameter from the URL query string
# e.g., /api/data?callback=myJsonpCallback
callback_name = request.args.get('callback')
if callback_name:
# If a callback is provided, this is a JSONP request
# 1. Convert the Python dictionary to a JSON string
json_data = jsonify(data)
# 2. Wrap the JSON string in the callback function call
# The .get_data() method returns the response body as a string
response_str = f"{callback_name}({json_data.get_data()})"
# 3. Set the correct content type for the response
return app.response_class(response_str, mimetype='application/javascript')
else:
# If no callback is provided, return a standard JSON response
return jsonify(data)
if __name__ == '__main__':
app.run(debug=True)
Run the server:
python app.py
The server will be running on http://127.0.0.1:5000.
Create a client HTML file (client.html):
This file will make the JSONP request.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">JSONP Client</title>
<style>
body { font-family: sans-serif; }
pre { background-color: #eee; padding: 10px; border-radius: 5px; }
</style>
</head>
<body>
<h1>JSONP Client</h1>
<p>Open the browser's developer console to see the response.</p>
<h2>Response Data:</h2>
<pre id="response"></pre>
<script>
function handleUserData(jsonResponse) {
console.log("Successfully received data via JSONP!");
console.log(jsonResponse);
// Display the data on the page
const preElement = document.getElementById('response');
preElement.textContent = JSON.stringify(jsonResponse, null, 2);
}
// Dynamically create a <script> tag to make the JSONP request
// This is the modern way to do it, though a simple <script src="..."> tag also works.
function makeJsonpRequest() {
const script = document.createElement('script');
const callbackName = 'handleUserData';
const url = 'http://127.0.0.1:5000/api/data?callback=' + callbackName;
script.src = url;
document.body.appendChild(script);
// Optional: Remove the script tag after it has executed
script.onload = function() {
document.body.removeChild(script);
};
}
// Make the request when the page loads
window.onload = makeJsonpRequest;
</script>
</body>
</html>
Test it:
Open client.html in your web browser. You will see the data appear on the page, and you'll see the "Successfully received data..." message in the developer console.
Method 2: Using Django (Example)
The logic is identical in Django. You just need to access the request parameters and format the response correctly.
Create a simple Django view (myapp/views.py):
from django.http import JsonResponse
from django.views.decorators.http import require_http_methods
# Sample data
DATA = {
"message": "Hello from the Django JSONP server!",
"timestamp": "2025-10-27T10:00:00Z"
}
@require_http_methods(["GET"])
def my_jsonp_view(request):
# Get the callback name from the GET parameters
callback = request.GET.get('callback')
if callback:
# This is a JSONP request
# 1. Get the JSON data as a string
json_data = JsonResponse(DATA).content.decode('utf-8')
# 2. Wrap it in the callback function
response_data = f"{callback}({json_data})"
# 3. Return a HttpResponse with the correct content type
from django.http import HttpResponse
return HttpResponse(response_data, content_type="application/javascript")
else:
# This is a standard AJAX request
return JsonResponse(DATA)
Configure the URL (myapp/urls.py):
from django.urls import path
from . import views
urlpatterns = [
path('api/django-data/', views.my_jsonp_view, name='django_jsonp'),
]
You would then make a request to http://your-django-app.com/api/django-data/?callback=handleDjangoData from your client-side JavaScript.
Important Considerations and Modern Alternatives
Security: JSONP is Insecure by Design
The biggest problem with JSONP is that it completely bypasses the Same-Origin Policy. If you trust api.someotherdomain.com, you are also trusting it to send any JavaScript code, not just a function call with your data. A malicious server could respond with maliciousCode(); instead of myDataHandler(...);, leading to a Cross-Site Scripting (XSS) attack on your application.
The Modern Alternative: CORS (Cross-Origin Resource Sharing)
For new applications, you should almost always use CORS instead of JSONP.
- How it works: CORS is a modern, standardized mechanism that allows servers to declare which origins are allowed to access their resources. The browser and server communicate via HTTP headers (
Access-Control-Allow-Origin, etc.). - Why it's better: It's more secure because it's based on explicit permission from the server. It's also more
