DocsAPI & Data PlatformFeaturesQuery via SDKs

Query Data via SDKs

Langfuse is open-source and all data tracked with Langfuse is accessible programmatically. The SDKs wrap the Public API so you can query data without writing raw HTTP requests.

Common use cases:

  • Collect production examples for few-shot prompts.
  • Export traces and generations for fine-tuning.
  • Build custom dashboards or downstream pipelines.
  • Programmatically create datasets from production data.

If you are new to Langfuse, familiarize yourself with the data model first.

New data is typically available for querying within 15-30 seconds of ingestion, though processing times may vary. Check status.langfuse.com if you encounter any issues.

Langfuse provides high-performance endpoints optimized for querying large datasets with cursor-based pagination and flexible field selection. These are the recommended defaults.

ResourceRecommended (high-performance)Legacy
Observationsapi.observationsapi.legacy.observations_v1 / observationsV1
Scoresapi.scoresapi.legacy.score_v1 / scoreV1
Metricsapi.metricsapi.legacy.metrics_v1 / metricsV1
Tracesapi.trace (unchanged)
⚠️

From Python SDK v4 and JS/TS SDK v5 onward, the high-performance endpoints are the defaults:

  • api.observations (formerly api.observations_v_2 / api.observationsV2)
  • api.scores (formerly api.score_v_2 / api.scoreV2)
  • api.metrics (formerly api.metrics_v_2 / api.metricsV2)

The old v2 aliases were removed in these major releases. Legacy v1 endpoints are now available under api.legacy.*.

If you need aggregated metrics (counts, costs, usage) rather than individual entities, consider the Metrics API which is optimized for aggregate queries and has higher rate limits.

Both SDKs authenticate via the LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY, and LANGFUSE_HOST environment variables. The api namespace is auto-generated from the Public API (OpenAPI spec). Method names mirror the REST resources and support filters and pagination.


Observations (recommended)

The observations endpoint is the primary and recommended way to query LLM call data from Langfuse. It covers all observation types — generations, spans, events, and more — with cursor-based pagination and selectable field groups.

Field selection

By default, the core and basic field groups are returned. Request additional groups via the fields parameter to include cost, token usage, model info, inputs/outputs, and more.

Field groupFields included
coreid, traceId, startTime, endTime, projectId, parentObservationId, type
basicname, level, statusMessage, version, environment, bookmarked, public, userId, sessionId
timecompletionStartTime, createdAt, updatedAt
ioinput, output
metadatametadata (truncated to 200 chars by default)
modelprovidedModelName, internalModelId, modelParameters
usageusageDetails, costDetails, totalCost
promptpromptId, promptName, promptVersion
metricslatency, timeToFirstToken

Advanced filtering with the filter parameter

For complex queries, use the structured filter parameter. It accepts a JSON string with an array of filter conditions. When provided, it takes precedence over individual query parameter filters.

Each filter condition has the following structure:

{
  "type": "string",
  "column": "name",
  "operator": "=",
  "value": "chat-completion"
}

Supported filter types and operators:

TypeOperators
string=, contains, does not contain, starts with, ends with
number=, >, <, >=, <=
datetime>, <, >=, <=
stringOptionsany of, none of
arrayOptionsany of, none of, all of
stringObject=, contains, does not contain, starts with, ends with (requires key)
numberObject=, >, <, >=, <= (requires key)
boolean=, <>
nullis null, is not null

Available columns:

  • Core fields: id, type, name, traceId, startTime, endTime, environment, level, statusMessage, version, userId, sessionId
  • Trace fields: traceName, traceTags / tags
  • Performance: latency, timeToFirstToken, tokensPerSecond
  • Token usage: inputTokens, outputTokens, totalTokens
  • Cost: inputCost, outputCost, totalCost
  • Model: model (alias: providedModelName), promptName, promptVersion
  • Metadata: metadata (use with stringObject, numberObject, or categoryOptions type and a key)

All conditions in the filter array are combined with AND logic.

Examples

pip install langfuse
from langfuse import get_client
 
langfuse = get_client()

Basic query

observations = langfuse.api.observations.get_many(limit=50)
 
for obs in observations.data:
    print(obs["id"], obs["type"], obs["name"])

Field selection

observations = langfuse.api.observations.get_many(
    fields="core,basic,usage,model,metrics",
    limit=50,
)
 
for obs in observations.data:
    print(obs["name"], obs.get("providedModelName"), obs.get("totalCost"), obs.get("latency"))

To retrieve full (non-truncated) metadata values for specific keys, use expand_metadata:

observations = langfuse.api.observations.get_many(
    fields="core,metadata",
    expand_metadata="system_prompt,config",
    limit=50,
)

Filter by observation type

Common types: GENERATION, SPAN, EVENT, AGENT, TOOL.

generations = langfuse.api.observations.get_many(
    type="GENERATION",
    fields="core,basic,usage,model",
    limit=100,
)

Filter by name

observations = langfuse.api.observations.get_many(
    name="chat-completion",
    type="GENERATION",
    limit=50,
)

Filter by trace

observations = langfuse.api.observations.get_many(
    trace_id="trace-abc-123",
    fields="core,basic,io,usage",
)

Filter by time range

from datetime import datetime, timedelta, timezone
 
observations = langfuse.api.observations.get_many(
    from_start_time=datetime.now(timezone.utc) - timedelta(hours=24),
    to_start_time=datetime.now(timezone.utc),
    type="GENERATION",
    fields="core,basic,usage",
    limit=100,
)

Filter by environment

observations = langfuse.api.observations.get_many(
    environment=["production", "staging"],
    type="GENERATION",
    limit=100,
)

Filter by trace tags

import json
 
observations = langfuse.api.observations.get_many(
    filter=json.dumps([
        {
            "type": "arrayOptions",
            "column": "traceTags",
            "operator": "any of",
            "value": ["production", "high-priority"]
        }
    ]),
    fields="core,basic,usage",
    limit=100,
)

Filter by metadata

Metadata filters use stringObject or numberObject types with a key to target specific metadata fields.

import json
 
observations = langfuse.api.observations.get_many(
    filter=json.dumps([
        {
            "type": "stringObject",
            "column": "metadata",
            "key": "customer_tier",
            "operator": "=",
            "value": "enterprise"
        }
    ]),
    fields="core,basic,metadata",
    expand_metadata="customer_tier",
    limit=100,
)

Filter by cost or latency

import json
 
expensive_slow_generations = langfuse.api.observations.get_many(
    filter=json.dumps([
        {"type": "string", "column": "type", "operator": "=", "value": "GENERATION"},
        {"type": "number", "column": "totalCost", "operator": ">=", "value": 0.10},
        {"type": "number", "column": "latency", "operator": ">=", "value": 5.0},
    ]),
    fields="core,basic,usage,model,metrics",
    limit=100,
)

Filter by model

import json
 
observations = langfuse.api.observations.get_many(
    filter=json.dumps([
        {"type": "string", "column": "model", "operator": "=", "value": "gpt-4o"},
    ]),
    fields="core,basic,usage,model",
    limit=100,
)

Combine multiple filters

import json
from datetime import datetime, timedelta, timezone
 
observations = langfuse.api.observations.get_many(
    filter=json.dumps([
        {"type": "string", "column": "type", "operator": "=", "value": "GENERATION"},
        {"type": "string", "column": "model", "operator": "starts with", "value": "gpt-4"},
        {"type": "arrayOptions", "column": "traceTags", "operator": "any of", "value": ["production"]},
        {"type": "stringObject", "column": "metadata", "key": "feature", "operator": "=", "value": "chat"},
        {
            "type": "datetime",
            "column": "startTime",
            "operator": ">=",
            "value": (datetime.now(timezone.utc) - timedelta(days=7)).isoformat()
        },
    ]),
    fields="core,basic,usage,model,metadata,metrics",
    limit=100,
)

Cursor-based pagination

The cursor is returned in response.meta.cursor and should be passed in subsequent requests to retrieve the next page.

all_observations = []
cursor = None
 
while True:
    response = langfuse.api.observations.get_many(
        type="GENERATION",
        fields="core,basic,usage",
        limit=500,
        cursor=cursor,
    )
    all_observations.extend(response.data)
 
    cursor = response.meta.cursor
    if not cursor:
        break
 
print(f"Fetched {len(all_observations)} observations")

Async usage

All endpoints are also available as async via async_api:

observations = await langfuse.async_api.observations.get_many(
    type="GENERATION",
    fields="core,basic,usage",
    limit=100,
)

Other endpoints

Traces

traces = langfuse.api.trace.list(
    limit=100,
    user_id="user_123",
    tags=["production"],
)
 
trace = langfuse.api.trace.get("trace-id")

The trace list endpoint supports filtering by user_id, session_id, name, tags, version, release, environment, from_timestamp/to_timestamp, and the structured filter parameter.

Fetching a single trace via trace.get() returns the trace with all its observations included. For querying observations at scale, prefer the observations endpoint instead.

Scores

scores = langfuse.api.scores.get_many(
    trace_id="trace-id",
    name="relevance",
    limit=100,
)
 
score = langfuse.api.scores.get_by_id("score-id")

The scores endpoint supports filtering by user_id, name, source, data_type, trace_id, observation_id, session_id, config_id, queue_id, trace_tags, environment, from_timestamp/to_timestamp, and the structured filter parameter.

Sessions

sessions = langfuse.api.sessions.list(limit=50)
session = langfuse.api.sessions.get("session-id")

Datasets

datasets = langfuse.api.datasets.list()
dataset = langfuse.api.datasets.get("dataset-name")
runs = langfuse.api.datasets.get_runs("dataset-name")

Prompts

See the prompt management documentation for details on fetching prompts.

Metrics

import json
 
result = langfuse.api.metrics.get(
    query=json.dumps({
        "view": "observations",
        "metrics": [{"measure": "totalCost", "aggregation": "sum"}],
        "dimensions": [{"field": "providedModelName"}],
        "filters": [],
        "fromTimestamp": "2025-05-01T00:00:00Z",
        "toTimestamp": "2025-05-31T00:00:00Z",
    })
)

See the Metrics API documentation for full details.


Legacy endpoints

The legacy v1 endpoints use page-based pagination and return a fixed set of fields. They remain available under api.legacy.* but are not recommended for new integrations.

legacy_observations = langfuse.api.legacy.observations_v1.get_many(
    trace_id="trace-id",
    type="GENERATION",
    page=1,
    limit=100,
)
legacy_observation = langfuse.api.legacy.observations_v1.get("observation-id")
 
legacy_scores = langfuse.api.legacy.score_v1.get(score_ids="score-id")

  • Public API reference — full OpenAPI spec for all endpoints.
  • Metrics API — optimized endpoint for aggregate queries (counts, costs, usage).
  • Blob Storage Export — scheduled data sync to S3, GCS, or Azure for large-scale exports.
  • Export from UI — download filtered data directly from the Langfuse dashboard.
  • Data Model — understand traces, observations, and scores.
Was this page helpful?