• Start

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)

Parameter

Type

Description

urlstr

The 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)

Parameter

Type

Description

urlstr

The 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)

Parameter

Type

Description

urlstr | None

An 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)

Parameter

Type

Description

namespacestr

The namespace to use.

databasestr

The 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)

Parameter

Type

Description

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)

Parameter

Type

Description

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)

Parameter

Type

Description

tokenstr

The 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)

Parameter

Type

Description

keystr

The name of the variable (without the

$

prefix).

value

Value

The 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)

Parameter

Type

Description

keystr

The 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)
Important

Behaviour change in v3.0. .query() now surfaces every statement result. When the server returns a single statement result it returns the result directly; when it returns multiple results it returns a tuple[Value, ...]. This fixes the silent-discard behaviour reported in issue #232.

Parameter

Type

Description

querystr

The SurrealQL query string to execute.

vars

dict[str,

Value

] | None

Variables 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)

Parameter

Type

Description

querystr

The SurrealQL query string to execute.

params

dict[str,

Value

] | None

Variables 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"},
)
Important

v3.0 builder pattern. .create(), .update(), .upsert(), .delete(), and .insert() return an awaitable (async) or lazy (sync) builder. The builder exposes chainable clause methods that map directly to SurrealQL clauses:

Calling .create(record, data) is sugar for .create(record).content(data). The standalone .merge(), .patch(), and .insert_relation() methods from v2.x have been removed.

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

Method Syntax
db.select(record)

Parameter

Type

Description

record

RecordIdType

A 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)

Parameter

Type

Description

record

RecordIdType

The table name or

RecordID

to create.

data

Value

| None

The 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)

Parameter

Type

Description

record

RecordIdType

The table name or

RecordID

to update.

data

Value

| None

The 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)

Parameter

Type

Description

record

RecordIdType

The table name or

RecordID

to upsert.

data

Value

| None

The 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)

Parameter

Type

Description

record

RecordIdType

The 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)

Parameter

Type

Description

tablestr | Table

The table to insert into.

data

Value

A 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)

Parameter

Type

Description

namestr

The fully-qualified function name, e.g.

"fn::increment"

.

args

list[

Value

] | None

Positional arguments forwarded to the function.

versionstr | None

Optional function version selector.

Returns: Value

Synchronous
result = db.run("fn::increment", [1])
Asynchronous
greeting = await db.run("fn::greet", ["world"])
Note

Live queries require a WebSocket connection (ws:// or wss://). HTTP and embedded connections raise UnsupportedFeatureError.

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)

Parameter

Type

Description

tablestr | Table

The table to watch for changes.

diffbool

If

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)

Parameter

Type

Description

query_uuidstr | UUID

The 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)

Parameter

Type

Description

query_uuidstr | UUID

The UUID of the live query to kill.

Returns: None

Synchronous
db.kill(query_uuid)
Asynchronous
await db.kill(query_uuid)
Note

Sessions require a WebSocket connection (ws:// or wss://). HTTP and embedded connections raise UnsupportedFeatureError.

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)

Parameter

Type

Description

session_idUUID

The session ID to detach from.

Returns: None

Synchronous
db.detach(session_id)
Asynchronous
await db.detach(session_id)
Note

Transactions require a WebSocket connection (ws:// or wss://). HTTP and embedded connections raise UnsupportedFeatureError.

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)

Parameter

Type

Description

session_idUUID | None

The 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)

Parameter

Type

Description

txn_idUUID

The transaction ID returned by

.begin()

.

session_idUUID | None

The 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)

Parameter

Type

Description

txn_idUUID

The transaction ID returned by

.begin()

.

session_idUUID | None

The 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?