Seamless Python ↔ JavaScript Bridge - Bidirectional, fully synchronized cross-language communication library.
License: MIT Python 3.7+ Node 12+
Break down language barriers and let Python and JavaScript talk to each other like old friends.
- ✅ Bidirectional Communication: JS → PY and PY → JS
- ✅ Synchronous Calls: Full Promise/await support
- ✅ Event-Based Architecture: Register, listen, and call methods
- ✅ Error Handling: Exception handling in both languages
- ✅ Type Safe: JSON serialization with validation
- ✅ Simple API: Just 3 core methods:
register(),listen(),call() - ✅ Zero Dependencies: No external packages required
- ✅ Lightweight: Minimal overhead, maximum performance
Ever wanted to combine Python's data processing power with JavaScript's UI capabilities? Or run ML models in Python while displaying results in Node.js? Crosspulse makes it effortless.
// JavaScript const result = await bridge.call("train_model", data); console.log("Accuracy:", result.accuracy);
# Python (automatically responds) bridge.register("train_model", train_ml_model)
That's it. No REST APIs, no HTTP servers, no complexity.
Download Manual:
JavaScript:
npm install crosspulse
Python:
pip install crosspulse
or Simply copy the files to your project:
crosspulse.py crosspulse.js
Requirements:
- Python 3.7+
- Node.js 12+
Call Python functions from JavaScript.
JavaScript side:
import Crosspulse from "crosspulse/src/crosspulse.js"; async function main() { // Create a bridge in "connect" mode const bridge = new Crosspulse("connect"); // Connect to the Python script await bridge.connect("python main.py"); // Call a Python function and get the result const result = await bridge.call("py_add", 10, 20); console.log(result); // 30 // Disconnect the bridge bridge.disconnect(); } // Run the main function main();
Python side:
import crosspulse # Create a bridge in "listen" mode bridge = crosspulse.Crosspulse(mode="listen") # Register a Python method that JS can call def py_add(a, b): return a + b bridge.register("py_add", py_add) # Start listening for incoming calls from JavaScript bridge.listen()
Run:
node app.js
Call JavaScript functions from Python.
Python side:
import crosspulse # Create a bridge in "connect" mode bridge = crosspulse.Crosspulse(mode="connect") # Connect to the JavaScript script bridge.connect("node app.js") # Call a JavaScript function and get the result result = bridge.call("js_multiply", 100, 50) print(result) # 5000 # Disconnect the bridge bridge.disconnect()
JavaScript side:
import Crosspulse from "crosspulse/src/crosspulse.js"; // Create a bridge in "listen" mode const bridge = new Crosspulse("listen"); // Register a JavaScript method that Python can call bridge.register("js_multiply", (a, b) => a * b); // Start listening for incoming calls from Python bridge.listen();
Run:
python main.py
Both languages can call each other simultaneously!
Python side:
import crosspulse # Create a bridge in "connect" mode bridge = crosspulse.Crosspulse(mode="connect") # Register Python methods that JavaScript can call def py_square(x): return x ** 2 def py_reverse(s): return s[::-1] bridge.register("py_square", py_square) bridge.register("py_reverse", py_reverse) # Connect to the JavaScript script bridge.connect("node app.js") # Call JavaScript methods result = bridge.call("js_capitalize", "hello world") print(result) # "HELLO WORLD" # JavaScript can call py_square() or py_reverse() one request at a time
JavaScript side:
import Crosspulse from "crosspulse/src/crosspulse.js"; // Create a bridge in "listen" mode const bridge = new Crosspulse("listen"); // Register JavaScript methods that Python can call bridge.register("js_capitalize", (str) => str.toUpperCase()); bridge.register("js_length", (str) => str.length); // Start listening for incoming calls from Python bridge.listen(); // Python can call these methods one request at a time // Incoming calls are automatically handled
from crosspulse import Crosspulse # Create instance bridge = Crosspulse(mode="listen") # Listen mode bridge = Crosspulse(mode="connect") # Connect mode # Register method bridge.register("method_name", callback_function) # Listen for calls (listen mode) bridge.listen() # Connect to target (connect mode) bridge.connect("node target_script.js") # Call remote method result = bridge.call("method_name", arg1, arg2) # Disconnect bridge.disconnect()
import Crosspulse from "crosspulse/src/crosspulse.js"; // Create instance const bridge = new Crosspulse("listen"); // Listen mode const bridge = new Crosspulse("connect"); // Connect mode // Register method bridge.register("method_name", (arg1, arg2) => { return result; }); // Listen for calls (listen mode) bridge.listen(); // Connect to target (connect mode) await bridge.connect("python target_script.py"); // Call remote method const result = await bridge.call("method_name", arg1, arg2); // Disconnect bridge.disconnect();
# data_processor.py import pandas as pd from crosspulse import Crosspulse bridge = Crosspulse("connect") bridge.connect("node visualizer.js") # Process data in Python df = pd.read_csv("sales_data.csv") insights = analyze_sales(df) # Visualize in JavaScript chart = bridge.call("create_chart", insights.to_dict()) print(f"Chart created: {chart}")
// visualizer.js import Crosspulse from "crosspulse/src/crosspulse.js"; const bridge = new Crosspulse("listen"); bridge.register("create_chart", (data) => { // Use Chart.js, D3.js, or any JS library const chart = generateChart(data); return chart.id; }); bridge.listen();
// ml_interface.js import Crosspulse from "crosspulse/src/crosspulse.js"; const bridge = new Crosspulse("connect"); async function trainModel(dataset) { await bridge.connect("python ml_model.py"); const progress = await bridge.call("train", dataset); console.log("Training progress:", progress); const predictions = await bridge.call("predict", testData); displayResults(predictions); }
# ml_model.py from sklearn.ensemble import RandomForestClassifier from crosspulse import Crosspulse bridge = Crosspulse("listen") model = RandomForestClassifier() def train_model(data): X, y = prepare_data(data) model.fit(X, y) return {"status": "trained", "accuracy": model.score(X, y)} bridge.register("train", train_model) bridge.listen()
# scraper.py from crosspulse import Crosspulse import requests from bs4 import BeautifulSoup bridge = Crosspulse("connect") def scrape_news(): # Scrape with Python data = scrape_website() # Send to JavaScript for display bridge.call("update_ui", data) bridge.connect("node server.js") scrape_news()
// electron_main.js import Crosspulse from "crosspulse/src/crosspulse.js"; const bridge = new Crosspulse("connect"); ipcMain.on("process-image", async (event, imagePath) => { await bridge.connect("python image_processor.py"); const processed = await bridge.call("enhance_image", imagePath); event.reply("image-ready", processed); });
try { const result = await bridge.call("risky_operation", data); console.log("Success:", result); } catch (error) { console.error("Python error:", error.message); }
try: result = bridge.call("risky_operation", data) print(f"Success: {result}") except Exception as e: print(f"JavaScript error: {e}")
// JavaScript const result = await bridge.call("process_user", { name: "John", age: 30, tags: ["developer", "python", "javascript"] });
# Python def process_user(user_data): return { "id": generate_id(), "name": user_data["name"], "processed": True } bridge.register("process_user", process_user)
# Python import time def long_running_task(duration): time.sleep(duration) return "Task completed" bridge.register("long_task", long_running_task)
// JavaScript const result = await bridge.call("long_task", 5); console.log(result); // "Task completed" (after 5 seconds)
| Use Case | Python Side | JavaScript Side |
|---|---|---|
| Web Scraping | BeautifulSoup, Scrapy | Display in React/Vue |
| Machine Learning | TensorFlow, PyTorch | Real-time UI updates |
| Data Analysis | Pandas, NumPy | Chart.js, D3.js |
| Image Processing | OpenCV, Pillow | Canvas, WebGL |
| File Processing | Parse Excel/PDF | Electron file picker |
| API Gateway | Flask/FastAPI alternative | Frontend communication |
| Desktop Apps | Backend logic | Electron UI |
| Automation | Selenium, automation | Control panel |
- Latency: ~5-10ms per call (local)
- Throughput: 1000+ calls/second
- Memory: Minimal overhead (<5MB)
- Scalability: Single process pair
For high-throughput scenarios, consider batching calls or using WebSocket alternatives.
- Crosspulse uses STDIN/STDOUT for IPC
- Only use with trusted code
- Validate all incoming data
- Don't expose to untrusted networks
- Consider sandboxing for production
# Make sure method is registered before listening bridge.register("my_method", my_function) bridge.listen() # Must be after register
// Ensure Python script is running await bridge.connect("python script.py"); // Python should be in listen mode
# Only use JSON-serializable types # ✅ str, int, float, list, dict, bool, None # ❌ Custom objects, functions, file handles
Contributions are welcome! Here's how:
git clone https://github.com/AnarDevStudio/crosspulse.git
cd crosspulseAreas to contribute:
- TypeScript definitions
- More examples
- Performance improvements
- Documentation
- Bug fixes
MIT License - Use it however you want!
MIT License
Copyright (c) 2026 AnarEsgerzade
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
If Crosspulse helps your project, give it a ⭐️ on GitHub!
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Email: anardevstudio@gmail.com
Built with ❤️ by developers who believe languages should work together, not apart.
Crosspulse - Where Python meets JavaScript. 🚀
Made by AnarEsgerzade🌷