Python SDK
Use the synchronous security_run.Client in Python 3.10+. Install from the repository and supply SECURITY_RUN_API_KEY as described in Authentication & installation.
The SDK provisions sessions and returns connection details. It does not execute remote commands or transfer files itself; use SSH/SFTP, an RDP client, or the browser for work inside the VM.
Quickstart with automatic cleanup
Save as quickstart.py:
from security_run import Client
with Client() as client:
with client.launch("ubuntu-24.04", ttl="30m") as session:
print("Session:", session.id)
print("IP:", session.ip)
print("Browser:", session.browser_url)
input("Open the browser URL. Press Enter here when finished: ")
Run it with python quickstart.py. launch() waits for readiness and loads native credentials. The inner context requests destruction when it exits, including when the work raises an exception. The outer context closes the client's HTTP connections.
Use windows-server-2025 for a Windows desktop. The browser URL requires sign-in as the owner. Do not exit the session context until your work is finished.
Credits and a quote
from security_run import Client
with Client() as client:
balance = client.credits()
quote = client.quote(
"ubuntu-24.04",
ttl="30m",
transfer_budget_credits=10,
)
print("Available:", balance["available_credits"], "credits")
print("Usage upper limit:", quote["max_credits"], "credits")
A quote does not create a VM or spend credits. This example returns an upper limit of 15 credits: 5 for compute and 10 for outbound data. Actual usage is deducted while the VM runs; the full quoted amount is not required at launch. The session stops earlier if credits run out.
Launch options
session = client.launch(
"ubuntu-24.04",
ttl="30m",
transfer_budget_credits=50,
wait=True,
timeout=900,
idempotency_key="case-482-linux",
)
| Parameter | Default | Meaning |
|---|---|---|
image |
Required | An exact ID from client.images(). |
ttl |
"30m" |
Duration string, or integer seconds. Range 300–14,400 seconds, subject to trial limits. |
transfer_budget_credits |
Server default: 50 | Integer outbound-credit budget from 10 to 500. |
wait |
True |
Wait for ready and fetch native credentials. |
timeout |
900 |
Readiness wait timeout, in seconds. |
idempotency_key |
Generated UUID | Reuse with identical options when retrying the same logical launch. |
Python timeouts are in seconds. They control the readiness/cleanup wait; individual API requests also have their own timeout and retries. A wait timeout does not cancel or destroy the server-side session.
The older transfer_budget_cents argument remains a compatibility alias. New code should use transfer_budget_credits and should not pass both.
Client and session reference
| Call or property | Result |
|---|---|
Client(api_key=None, base_url=None) |
A client using explicit values or the environment. |
client.images() |
List of image dictionaries, including resource details and pricing. |
client.credits() |
Credit account dictionary. |
client.quote(image, ttl="30m", transfer_budget_credits=50) |
Usage upper limit and rate dictionary. |
client.launch(image, ...) |
A Session. |
client.list() |
List of Session objects; follows pagination automatically. |
client.get(session_id) |
A session with its current state. |
client.close() |
Close local HTTP resources; does not destroy VMs. |
session.id, .ip, .state, .browser_url |
Current cached session fields. IP may be None before readiness. |
session.refresh() |
Fetch current state, update the object, return the same session. |
session.credentials |
A copy of the native credentials; fetches them if not already loaded. Requires readiness. |
session.to_dict() |
A deep copy of the cached response. May contain credentials. |
session.destroy(wait=True, timeout=180) |
Request teardown; by default wait up to 180 seconds for a terminal state. |
There is no session.run() or session.exec() method. Use the native connection details with your chosen SSH/RDP tooling.
Inspect existing sessions
from security_run import Client
with Client() as client:
for session in client.list():
print(session.id, session.state, session.browser_url)
session = client.get("ses_YOUR_SESSION_ID")
if session.state == "ready":
username = session.credentials["username"]
print("Ready:", session.ip, username)
session.destroy()
Retrieving credentials is an owner-authorized operation. Linux supplies username, private_key, and host_public_key; Windows supplies username, password, and certificate_fingerprint. Use the returned host key/fingerprint to verify a native connection, and never log the full credential dictionary.
Return immediately, then reconnect
Use wait=False when another process will track startup. Save the ID durably before doing other work:
from pathlib import Path
from security_run import Client
with Client() as client:
session = client.launch("ubuntu-24.04", wait=False, ttl="30m")
Path("session-id.txt").write_text(session.id)
print(session.browser_url)
Later, call client.get(saved_id) and session.refresh() to track readiness. Access session.credentials only once session.state == "ready". A refresh() response does not include native secrets; the next credentials access will fetch them again.
This pattern intentionally leaves the session running. Arrange a cleanup path in the process that owns the work; otherwise it runs until its absolute expiry.
Handle timeouts and uncertain requests
from security_run import Client, SessionError
with Client() as client:
try:
with client.launch(
"ubuntu-24.04",
ttl="30m",
timeout=120,
idempotency_key="case-482-linux",
) as session:
print(session.browser_url)
except SessionError as error:
print(str(error))
if error.session_id:
# This workflow chooses to stop if startup exceeds its deadline.
client.get(error.session_id).destroy()
If launch fails before entering the session context, the context cannot clean it up. Readiness errors carry session_id; use it to inspect or destroy the session. If a transport error happened before the client received an ID, retry using the original idempotency key and unchanged options to resolve the existing request.
Inside a session context, cleanup is attempted even when your work fails. If both work and cleanup fail, the original work error is preserved; on Python 3.11+ a note records the cleanup failure. Inspect the session by ID if teardown could not be confirmed.
For async Python applications, this client is synchronous: run blocking operations in a worker thread, or call the HTTP API with your own async client.
Machine sizes
Basic Linux terminals default to Small: 2 vCPUs and 2 GiB RAM at 10 credits/hour. Select Standard for 4 GiB at 40 credits/hour: client.launch("ubuntu-24.04", size="standard"). Security desktops and Windows support Standard only (4 GiB, 15 credits/hour). SDK sessions retain their explicit TTL and are not subject to browser inactivity cleanup by default.
Preconfigured security desktops
Use parrot, sift, remnux or flare as the image ID with the same launch and cleanup methods. Standard size is selected automatically. For example: session = client.launch("remnux", ttl="30m")
The Linux desktops return both credentials.password for RDP and credentials.private_key for SSH. The connection response includes port: 3389 and ssh_port: 22. Use credentials.username instead of assuming a login name. FLARE-VM provides RDP on Windows Server 2022.