Magic-Wormhole
Magic-Wormhole is a Python library and command-line tool for securely transferring arbitrary data (files, directories, or text) between computers using a short, human-speakable 'wormhole code'. It leverages PAKE (Password-Authenticated Key Exchange) for secure key establishment. It is actively maintained at version 0.23.0 with a focus on security, reliability, and ease of use, releasing updates on a moderate cadence.
Common errors
-
twisted.internet.error.DNSLookupError: Hostname 'relay.magic-wormhole.io' could not be resolved
cause The system was unable to resolve the hostname of the default `magic-wormhole` relay server, likely due to network connectivity issues, misconfigured DNS, or a restrictive firewall.fixVerify your internet connection and DNS settings. Check firewall rules to ensure outgoing WebSocket connections (port 443 or 80 for `wss://` or `ws://` respectively, or port 4000 for specific relay setup) are allowed. You might need to specify a custom relay server if the default one is consistently unreachable. -
TypeError: object NoneType can't be used in 'await' expression
cause This typically occurs when an asynchronous function or method is called without the `await` keyword, causing it to return a `coroutine` object which then gets lost, or if a non-async function is mistakenly awaited.fixEnsure all `magic_wormhole` API calls (e.g., `w.get_code()`, `w.send_data()`) are prefixed with `await`. Also, confirm that the function containing these calls is declared with `async def` and is ultimately run by `asyncio.run()`. -
Wormhole negotiation failed: recipient cancelled
cause The remote party (recipient) closed their `magic-wormhole` client or explicitly cancelled the transfer before the negotiation could complete or the data transfer could begin.fixCommunicate with the recipient to ensure they are ready and have not cancelled the operation. Both sender and receiver should restart their respective `magic-wormhole` processes, typically with a new wormhole code.
Warnings
- gotcha By default, `magic-wormhole` relies on a public relay server for initial connection bootstrapping. If this server is unreachable due to network issues, firewalls, or outages, connections will fail.
- gotcha Programmatic use of the `magic-wormhole` API is inherently asynchronous and requires managing an event loop (e.g., `asyncio`). Attempting to call async methods without `await` or outside an `async` context will result in runtime errors.
- gotcha Wormhole codes are designed for one-time, ephemeral use. While the library might allow it, reusing a generated code for multiple, separate transfers or across long durations is not the intended use and can lead to unexpected behavior or security issues.
Install
-
pip install magic-wormhole
Imports
- Wormhole
from magic_wormhole.api import Wormhole
Quickstart
import asyncio
from magic_wormhole.api import Wormhole
async def send_data_example():
w = Wormhole()
code = await w.get_code()
print(f"Your wormhole code is: {code}")
print("Waiting for recipient to connect...")
# In a real scenario, you'd wait for connection confirmation before sending sensitive data.
# The 'send_data' or 'send_file' automatically handles the rendezvous.
data_to_send = b"Hello, magic wormhole!"
print(f"Sending: '{data_to_send.decode()}'")
await w.send_data(data_to_send)
print("Data sent.")
# The wormhole object must be closed to release resources and ensure clean exit.
await w.close()
if __name__ == "__main__":
# This runs the asynchronous example using asyncio
asyncio.run(send_data_example())