• Start

Languages

/

Python

/

API Reference

/

Core

Surreal

The Surreal and AsyncSurreal factory functions are the main entry points for connecting to and interacting with a SurrealDB instance from Python.

The Surreal and AsyncSurreal factory functions create a connection to a SurrealDB instance. They inspect the URL scheme and return the appropriate connection class (WebSocket, HTTP, or embedded), so you use the same interface regardless of protocol.

Surreal(url) returns a blocking (synchronous) connection. AsyncSurreal(url) returns an asynchronous connection. Both expose the same set of methods; the async variants must be awaited.

Source: surrealdb.py

Creates a synchronous connection based on the URL scheme.

Syntax

from surrealdb import Surreal

db = Surreal(url)
ParameterTypeDescription
url strThe connection URL. The scheme determines the connection type.

Returns: BlockingWsSurrealConnection | BlockingHttpSurrealConnection | BlockingEmbeddedSurrealConnection

Creates an asynchronous connection based on the URL scheme.

Syntax

from surrealdb import AsyncSurreal

db = AsyncSurreal(url)
ParameterTypeDescription
url strThe connection URL. The scheme determines the connection type.

Returns: AsyncWsSurrealConnection | AsyncHttpSurrealConnection | AsyncEmbeddedSurrealConnection

SchemeConnection TypeDescription
ws://, wss://WebSocketFull-featured stateful connection. Supports live queries, sessions, and transactions.
http://, https://HTTPStateless connection. Each request is independent.
mem://, memory://Embedded (in-memory)In-process database that does not persist data.
file://, surrealkv://Embedded (on-disk)In-process database backed by SurrealKV storage.

WebSocket

from surrealdb import Surreal

db = Surreal("ws://localhost:8000")

HTTP

from surrealdb import Surreal

db = Surreal("https://cloud.surrealdb.com")

Embedded in-memory

from surrealdb import Surreal

db = Surreal("mem://")

Embedded on-disk

from surrealdb import Surreal

db = Surreal("surrealkv://path/to/database")

Async WebSocket

from surrealdb import AsyncSurreal

db = AsyncSurreal("ws://localhost:8000")

Opens the connection to the SurrealDB instance. The URL can optionally be overridden here.

Method Syntax

db.connect(url)
ParameterTypeDescription
url str | NoneAn optional URL to override the one provided to the factory function. Defaults to None.

Returns: None

Synchronous

from surrealdb import Surreal

db = Surreal("ws://localhost:8000")
db.connect()

Asynchronous

from surrealdb import AsyncSurreal

db = AsyncSurreal("ws://localhost:8000")
await db.connect()

Override URL

db = Surreal("ws://localhost:8000")
db.connect("ws://other-host:8000")

Closes the active connection and releases resources.

Method Syntax

db.close()

Returns: None

Synchronous

db.close()

Asynchronous

await db.close()

Switches to a specific namespace and database.

Method Syntax

db.use(namespace, database)
ParameterTypeDescription
namespace strThe namespace to use.
database strThe database to use.

Returns: None

Synchronous

db.use("my_namespace", "my_database")

Asynchronous

await db.use("my_namespace", "my_database")

Returns the version string of the connected SurrealDB instance.

Method Syntax

db.version()

Returns: str

Synchronous

ver = db.version()
print(ver) # e.g. "surrealdb-2.2.0"

Asynchronous

ver = await db.version()
print(ver)

Signs up a user to a specific access method.

Method Syntax

db.signup(vars)
ParameterTypeDescription
vars dict[str, Value]Variables used for signup, including namespace, database, access, and any additional fields required by the access method.

Returns: Tokens

Synchronous

token = db.signup({
"namespace": "my_namespace",
"database": "my_database",
"access": "user_access",
"email": "user@example.com",
"password": "s3cret",
})

Asynchronous

token = await db.signup({
"namespace": "my_namespace",
"database": "my_database",
"access": "user_access",
"email": "user@example.com",
"password": "s3cret",
})

Signs in to the database with the given credentials.

Method Syntax

db.signin(vars)
ParameterTypeDescription
vars dict[str, Value]Credentials for authentication. For root access, provide username and password. For scoped access, also include namespace, database, and access.

Returns: Tokens

Root signin (sync)

token = db.signin({
"username": "root",
"password": "root",
})

Root signin (async)

token = await db.signin({
"username": "root",
"password": "root",
})

Scoped signin

token = db.signin({
"namespace": "my_namespace",
"database": "my_database",
"access": "user_access",
"email": "user@example.com",
"password": "s3cret",
})

Authenticates the current connection with a JWT token.

Method Syntax

db.authenticate(token)
ParameterTypeDescription
token strThe JWT token to authenticate with.

Returns: None

Synchronous

db.authenticate("eyJhbGciOiJIUzI1NiIs...")

Asynchronous

await db.authenticate("eyJhbGciOiJIUzI1NiIs...")

Invalidates the authentication for the current connection, removing the associated JWT token.

Method Syntax

db.invalidate()

Returns: None

Synchronous

db.invalidate()

Asynchronous

await db.invalidate()

Returns the record of the currently authenticated user.

Method Syntax

db.info()

Returns: Value

Synchronous

user = db.info()
print(user) # e.g. {"id": "users:john", "email": "john@example.com"}

Asynchronous

user = await db.info()

Defines a variable on the current connection that can be used in subsequent queries.

Method Syntax

db.let(key, value)
ParameterTypeDescription
key strThe name of the variable (without the $ prefix).
value ValueThe value to assign to the variable.

Returns: None

Synchronous

db.let("user_id", RecordID("users", "john"))
result = db.query("SELECT * FROM users WHERE id = $user_id")

Asynchronous

await db.let("user_id", RecordID("users", "john"))
result = await db.query("SELECT * FROM users WHERE id = $user_id")

Removes a previously defined variable from the current connection.

Method Syntax

db.unset(key)
ParameterTypeDescription
key strThe name of the variable to remove.

Returns: None

Synchronous

db.unset("user_id")

Asynchronous

await db.unset("user_id")

Runs a set of SurrealQL statements against the database. Returns an awaitable (async) or lazy (sync) builder.

Method Syntax

db.query(query, vars)
ParameterTypeDescription
query strThe SurrealQL query string to execute.
vars dict[str, Value] | NoneVariables to bind into the query. Defaults to None.

Returns: Value for a single-statement query, otherwise tuple[Value, ...] of statement results.

The returned object also exposes .into(cls) which maps the N statement results positionally onto the fields of a dataclass (or any class accepting keyword arguments).

Single statement (async)

result = await db.query(
"SELECT * FROM users WHERE age > $min_age",
{"min_age": 18},
)

Multi-statement returns tuple

people, count = await db.query(
"SELECT * FROM person; SELECT count() FROM person GROUP ALL"
)

Map results onto a dataclass

from dataclasses import dataclass

@dataclass
class Stats:
people: list
count: list

stats = await db.query(
"SELECT * FROM person; SELECT count() FROM person GROUP ALL"
).into(Stats)

Synchronous lazy builder

# The sync builder auto-executes when consumed (indexed, iterated, compared, etc.).
# For fire-and-forget statements call .execute() explicitly.
people = db.query("SELECT * FROM users")
print(len(people))
db.query("DELETE temp_data;").execute()

Runs a set of SurrealQL statements and returns the raw RPC response, including per-statement results, statuses, and execution times. Unlike .query(), errors in individual statements are returned in the response rather than raised as exceptions.

Method Syntax

db.query_raw(query, params)
ParameterTypeDescription
query strThe SurrealQL query string to execute.
params dict[str, Value] | NoneVariables to bind into the query. Defaults to None.

Returns: dict[str, Any]

Synchronous

raw = db.query_raw(
"CREATE users SET name = $name; SELECT * FROM users;",
{"name": "John"},
)

for statement in raw["result"]:
print(statement["status"], statement["time"])

Asynchronous

raw = await db.query_raw(
"CREATE users SET name = $name; SELECT * FROM users;",
{"name": "John"},
)

Selects all records in a table, or a specific record by its ID.

Method Syntax

db.select(record)
ParameterTypeDescription
record RecordIdTypeA table name (str) or a RecordID to select.

Returns: Value

Synchronous

users = db.select("users")

user = db.select(RecordID("users", "john"))

Asynchronous

users = await db.select("users")

user = await db.select(RecordID("users", "john"))

Creates a record in a table. If a RecordID is passed, the record is created with that specific ID. If a table name is passed, a random ID is generated.

Method Syntax

db.create(record, data)
ParameterTypeDescription
record RecordIdTypeThe table name or RecordID to create.
data Value | NoneThe record data. Defaults to None.

Returns: Value

Synchronous

user = db.create("users", {
"name": "John",
"email": "john@example.com",
})

product = db.create(RecordID("products", "apple"), {
"name": "Apple",
"price": 1.50,
})

Asynchronous

user = await db.create("users", {
"name": "John",
"email": "john@example.com",
})

Replaces the entire record with the given data. Fields not present in data are removed.

Method Syntax

db.update(record, data)
ParameterTypeDescription
record RecordIdTypeThe table name or RecordID to update.
data Value | NoneThe new record data. Defaults to None.

Returns: Value

Synchronous

db.update(RecordID("users", "john"), {
"name": "John Doe",
"email": "john.doe@example.com",
})

Asynchronous

await db.update(RecordID("users", "john"), {
"name": "John Doe",
"email": "john.doe@example.com",
})

Updates an existing record or creates a new one if it does not exist. Replaces the entire record content.

Method Syntax

db.upsert(record, data)
ParameterTypeDescription
record RecordIdTypeThe table name or RecordID to upsert.
data Value | NoneThe record data. Defaults to None.

Returns: Value

Synchronous

db.upsert(RecordID("users", "john"), {
"name": "John",
"email": "john@example.com",
})

Asynchronous

await db.upsert(RecordID("users", "john"), {
"name": "John",
"email": "john@example.com",
})

.merge(data) is a builder clause method - chain it on .update(), .upsert(), or .create(). It compiles to ... MERGE $data and preserves any existing fields not present in data.

Synchronous

db.update(RecordID("users", "john")).merge({"age": 32})

Asynchronous

await db.update(RecordID("users", "john")).merge({"age": 32})

.patch(data) is a builder clause method - chain it on .update(), .upsert(), or .create(). It compiles to ... PATCH $data and applies JSON Patch operations.

Synchronous

db.update(RecordID("users", "john")).patch([
{"op": "replace", "path": "/email", "value": "new@example.com"},
{"op": "add", "path": "/verified", "value": True},
])

Asynchronous

await db.update(RecordID("users", "john")).patch([
{"op": "replace", "path": "/email", "value": "new@example.com"},
])

Deletes all records in a table, or a specific record by its ID.

Method Syntax

db.delete(record)
ParameterTypeDescription
record RecordIdTypeThe table name or RecordID to delete.

Returns: Value

Synchronous

db.delete(RecordID("users", "john"))

db.delete("temp_data")

Asynchronous

await db.delete(RecordID("users", "john"))

Inserts one or more records into a table.

Method Syntax

db.insert(table, data)
ParameterTypeDescription
table str | TableThe table to insert into.
data ValueA single record dict or a list of record dicts to insert.

Returns: Value

Synchronous

db.insert("users", {"name": "Alice", "email": "alice@example.com"})

db.insert("users", [
{"name": "Bob", "email": "bob@example.com"},
{"name": "Charlie", "email": "charlie@example.com"},
])

Asynchronous

await db.insert("users", {"name": "Alice", "email": "alice@example.com"})

The standalone .insert_relation() method from v2.x has been removed. Use .insert(table, data, relation=True) or chain .relation() on the insert builder to issue an INSERT RELATION INTO statement.

Synchronous

db.insert("likes", {
"in": RecordID("users", "alice"),
"out": RecordID("posts", "post1"),
}, relation=True)

# Or via the builder:
db.insert("likes").relation().content({
"in": RecordID("users", "alice"),
"out": RecordID("posts", "post1"),
})

Asynchronous

await db.insert("likes", {
"in": RecordID("users", "alice"),
"out": RecordID("posts", "post1"),
}, relation=True)

Calls a SurrealDB function and returns its result. The function name typically uses the fn:: prefix for user-defined functions or namespace prefixes for built-ins.

Method Syntax

db.run(name, args, version)
ParameterTypeDescription
name strThe fully-qualified function name, e.g. "fn::increment".
args list[Value] | NonePositional arguments forwarded to the function.
version str | NoneOptional function version selector.

Returns: Value

Synchronous

result = db.run("fn::increment", [1])

Asynchronous

greeting = await db.run("fn::greet", ["world"])

Initiates a live query for a table. Returns a UUID that identifies the live query and can be passed to .subscribe_live() and .kill().

Method Syntax

db.live(table, diff)
ParameterTypeDescription
table str | TableThe table to watch for changes.
diff boolIf True, notifications include JSON Patch diffs instead of full records. Defaults to False.

Returns: UUID

Synchronous

query_uuid = db.live("users")

query_uuid = db.live("users", diff=True)

Asynchronous

query_uuid = await db.live("users")

Returns a generator that yields live query notifications for the given query UUID. Each notification is a dict containing the action ("CREATE", "UPDATE", "DELETE"), the record data, and the record ID.

Method Syntax

db.subscribe_live(query_uuid)
ParameterTypeDescription
query_uuid str | UUIDThe UUID of the live query returned by .live().

Returns (sync): Generator[dict[str, Value], None, None] Returns (async): AsyncGenerator[dict[str, Value], None]

Synchronous

query_uuid = db.live("users")

for notification in db.subscribe_live(query_uuid):
print(notification["action"], notification["result"])

Asynchronous

query_uuid = await db.live("users")

async for notification in db.subscribe_live(query_uuid):
print(notification["action"], notification["result"])

Terminates a running live query by its UUID.

Method Syntax

db.kill(query_uuid)
ParameterTypeDescription
query_uuid str | UUIDThe UUID of the live query to kill.

Returns: None

Synchronous

db.kill(query_uuid)

Asynchronous

await db.kill(query_uuid)

Sessions allow you to create isolated contexts on a single connection, each with its own namespace, database, variables, and authentication state.

Creates a new isolated session on the current connection.

Method Syntax

db.new_session()

Returns (sync): BlockingSurrealSession Returns (async): AsyncSurrealSession

Synchronous

session = db.new_session()
session.use("other_ns", "other_db")
result = session.select("users")

Asynchronous

session = await db.new_session()
await session.use("other_ns", "other_db")
result = await session.select("users")

Attaches to the server-side session associated with this connection and returns its session ID.

Method Syntax

db.attach()

Returns: UUID

Synchronous

session_id = db.attach()

Asynchronous

session_id = await db.attach()

Detaches from a server-side session.

Method Syntax

db.detach(session_id)
ParameterTypeDescription
session_id UUIDThe session ID to detach from.

Returns: None

Synchronous

db.detach(session_id)

Asynchronous

await db.detach(session_id)

Transactions let you group multiple operations into an atomic unit. Changes are only applied when the transaction is committed, and can be rolled back with cancel.

Begins a new transaction, optionally within a specific session.

Method Syntax

db.begin(session_id)
ParameterTypeDescription
session_id UUID | NoneThe session to start the transaction in. If None, uses the default session. Defaults to None.

Returns: UUID — the transaction ID

Synchronous

txn_id = db.begin()

Asynchronous

txn_id = await db.begin()

Within a session

session_id = db.attach()
txn_id = db.begin(session_id)

Commits a transaction, applying all changes made within it.

Method Syntax

db.commit(txn_id, session_id)
ParameterTypeDescription
txn_id UUIDThe transaction ID returned by .begin().
session_id UUID | NoneThe session the transaction belongs to. Defaults to None.

Returns: None

Synchronous

txn_id = db.begin()
db.query("CREATE users SET name = 'Alice'")
db.commit(txn_id)

Asynchronous

txn_id = await db.begin()
await db.query("CREATE users SET name = 'Alice'")
await db.commit(txn_id)

Cancels a transaction, discarding all changes made within it.

Method Syntax

db.cancel(txn_id, session_id)
ParameterTypeDescription
txn_id UUIDThe transaction ID returned by .begin().
session_id UUID | NoneThe session the transaction belongs to. Defaults to None.

Returns: None

Synchronous

txn_id = db.begin()
db.query("DELETE users")
db.cancel(txn_id)

Asynchronous

txn_id = await db.begin()
await db.query("DELETE users")
await db.cancel(txn_id)

Both Surreal and AsyncSurreal support the context manager protocol. The connection is automatically opened on entry and closed on exit.

Synchronous context manager

from surrealdb import Surreal

with Surreal("ws://localhost:8000") as db:
db.use("my_namespace", "my_database")
db.signin({"username": "root", "password": "root"})
users = db.select("users")

Asynchronous context manager

from surrealdb import AsyncSurreal

async with AsyncSurreal("ws://localhost:8000") as db:
await db.use("my_namespace", "my_database")
await db.signin({"username": "root", "password": "root"})
users = await db.select("users")

Full workflow (sync)

from surrealdb import Surreal, RecordID

with Surreal("ws://localhost:8000") as db:
db.use("shop", "inventory")
db.signin({"username": "root", "password": "root"})

db.create("products", {"name": "Laptop", "price": 999.99})
db.create("products", {"name": "Mouse", "price": 29.99})

products = db.select("products")
print("All products:", products)

cheap = db.query(
"SELECT * FROM products WHERE price < $max",
{"max": 100},
)
print("Affordable:", cheap)

db.update(RecordID("products", products[0]["id"].id)).merge({"stock": 50})

db.delete(RecordID("products", products[1]["id"].id))

Full workflow (async)

import asyncio
from surrealdb import AsyncSurreal, RecordID

async def main():
async with AsyncSurreal("ws://localhost:8000") as db:
await db.use("shop", "inventory")
await db.signin({"username": "root", "password": "root"})

await db.create("products", {"name": "Laptop", "price": 999.99})

products = await db.select("products")
print("Products:", products)

asyncio.run(main())

Was this page helpful?