- Connect to a remote Turso database
- Execute SQL queries using SQL over HTTP
Match the driver to your database engine:
@tursodatabase/serverless for Turso databases, @libsql/client for libSQL databases.
- @tursodatabase/serverless
- @libsql/client
- Raw HTTP
The For compatibility with the libSQL client API, use the compat module:
@tursodatabase/serverless package connects to Turso using only the fetch API — no native dependencies, making it the smallest option for edge and serverless runtimes.1
Install
npm install @tursodatabase/serverless
2
Connect and query
import { connect } from "@tursodatabase/serverless";
const conn = connect({
url: process.env.TURSO_DATABASE_URL,
authToken: process.env.TURSO_AUTH_TOKEN,
});
const stmt = await conn.prepare("SELECT * FROM users WHERE id = ?");
const row = await stmt.get([123]);
import { createClient } from "@tursodatabase/serverless/compat";
const client = createClient({
url: process.env.TURSO_DATABASE_URL,
authToken: process.env.TURSO_AUTH_TOKEN,
});
const result = await client.execute("SELECT * FROM users WHERE id = ?", [123]);
The
@libsql/client package is the production-ready libSQL driver used across the Turso ecosystem. Use the /web import for serverless and edge runtimes.1
Install
npm install @libsql/client
2
Connect and query
import { createClient } from "@libsql/client/web";
const client = createClient({
url: process.env.TURSO_DATABASE_URL!,
authToken: process.env.TURSO_AUTH_TOKEN!,
});
const result = await client.execute({
sql: "SELECT * FROM users WHERE id = ?",
args: [123],
});
Use
@libsql/client/web instead of @libsql/client for edge and serverless runtimes. The /web import uses the HTTP protocol.You can also send queries directly over HTTP using any HTTP client.
1
Create HTTP Database URL
Using the Turso CLI or Platform API, fetch your database URL:
turso db show <database-name> --http-url
Append
/v2/pipeline to the URL and continue.2
Create Database Auth Token
Using the Turso CLI or Platform API, create a new auth token for your database:
turso db tokens create <database-name>
3
Create JSON Request Payload
We’ll be sending the query using JSON, so let’s create a JSON payload that executes a SQL statement and closes the connection immediately:
{
"requests": [
{ "type": "execute", "stmt": { "sql": "SELECT * FROM users" } },
{ "type": "close" }
]
}
Make sure to update the
stmt.sql to select from a table you already have.Bound parameter examples included on the Reference Page,4
Execute HTTP Request
Depending on your language, you can use a HTTP client library to send the request to the URL you created as well as the
If you need to use placeholders for values, you can do that:
Authorization header set to the token you created, and the request body as JSON with your SQL statement.You must append to the Base URL the actual pipeline URL that accepts requests — /v2/pipeline.const url = "https://[databaseName]-[organizationSlug].turso.io/v2/pipeline";
const authToken = "...";
fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${authToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
requests: [
{ type: "execute", stmt: { sql: "SELECT * FROM users" } },
{ type: "close" },
],
}),
})
.then((res) => res.json())
.then((data) => console.log(data))
.catch((err) => console.log(err));
require 'net/http'
require 'json'
require 'uri'
url = "https://[databaseName]-[organizationSlug].turso.io/v2/pipeline"
auth_token = "..."
uri = URI(url)
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer #{auth_token}"
request["Content-Type"] = "application/json"
request.body = JSON.generate({
"requests": [
{ "type": "execute", "stmt": { "sql": "SELECT * FROM users" } },
{ "type": "close" }
]
})
begin
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(request)
end
puts JSON.parse(response.body)
rescue => e
puts e.message
end
Response
Response
The response will be a JSON object with a
results array containing the results of your query that looks something like this:{
"baton": null,
"base_url": null,
"results": [
{
"type": "ok",
"response": {
"type": "execute",
"result": {
"cols": [],
"rows": [],
"affected_row_count": 0,
"last_insert_rowid": null,
"replication_index": "1"
}
}
},
{
"type": "ok",
"response": {
"type": "close"
}
}
]
}
{
"type": "execute",
"stmt": {
"sql": "SELECT * FROM users WHERE id = ?",
"args": [
{
"type": "integer",
"value": "1"
}
]
}
}
{
"type": "execute",
"stmt": {
"sql": "SELECT * FROM users WHERE name = :name OR name = $second_name OR name = @third_name",
"named_args": [
{
"name": "name",
"value": {
"type": "text",
"value": "Turso"
}
},
{
"name": "second_name",
"value": {
"type": "text",
"value": "Not Turso"
}
},
{
"name": "third_name",
"value": {
"type": "text",
"value": "Maybe Turso"
}
}
]
}
}
The
type field within each arg corresponds to the column datatype and can be one of the following: null, integer, float, text, or blob.In JSON, the
value is a String to avoid losing precision, because some
JSON implementations treat all numbers as 64-bit floats.