Langfuse records what happens inside an AI application. Wrap your code with its SDK, or swap in its drop-in OpenAI client, and every model call, retrieval step, tool call and agent turn lands in a trace you can open in a web UI with inputs, outputs, latency, token counts and cost. When an answer goes wrong in production, you can see the exact prompt the model received and jump into a playground to work on it.
Around the tracing sit the parts teams otherwise build by hand: versioned prompt management, so prompts change without a redeploy; datasets for regression testing; and evaluations by LLM-as-a-judge, code, user feedback or manual labeling. It integrates with LangChain, LlamaIndex, the Vercel AI SDK, LiteLLM, Dify, Open WebUI and many of the other tools on this list.
The code is MIT licensed apart from the ee folders, which hold enterprise features under their own licence, and the project has about 35,000 stars. Langfuse has been part of ClickHouse since January 2026, and the self-hosted stack stores traces in the ClickHouse database. A managed cloud version has a free tier.
- Repository: github.com/langfuse/langfuse
- Licence: custom (Other)
- Language: TypeScript. Stars: 35.3K. Forks: 3,911. Last push: Oct 2, 2026.
- Scan: safe, Oct 2, 2026, commit f75c661
Who it is for
Developers and teams running LLM features in production who need to debug individual requests, track cost and quality over time, and manage prompts outside the codebase, especially those who want that data on their own servers.
Getting started
1. Self-host it on one machine with Docker Compose (UI on http://localhost:3000)
git clone --depth=1 https://github.com/langfuse/langfuse.git && cd langfuse && docker compose up2. Install the Python SDK in your app
pip install langfuse openai3. Point the SDK at your instance with keys from the project settings
export LANGFUSE_PUBLIC_KEY=pk-lf-... LANGFUSE_SECRET_KEY=sk-lf-... LANGFUSE_BASE_URL=http://localhost:3000The Docker Compose setup is for one machine; the docs recommend Kubernetes with Helm for production, and there are Terraform templates for AWS, Azure and GCP. The compose file ships placeholder secrets marked CHANGEME, so replace them before the instance is reachable from a network, and set TELEMETRY_ENABLED=false if you do not want usage counts reported to Langfuse. Langfuse Cloud skips all of this.
Safety scan
We cloned langfuse/langfuse at commit f75c661 on Oct 2, 2026 and ran the checks described on the GitHub Tools page: credential patterns, decode-and-execute code, install-time scripts, committed binaries, risky CI workflows, every host the code talks to, known vulnerabilities in pinned dependencies, and project hygiene. A person read every hit. This is what we found.
- No committed binaries across 6,525 files and about 1.3 million lines, almost all TypeScript. The 23 secret hits are test fixtures: Slack tokens such as xoxb-test-token in the Slack integration tests and placeholder PEM keys in AI-gateway and LLM-connection tests. The eight bare-IP URLs are tests proving that LLM base URLs and webhook targets are validated, using 1.1.1.1, a multicast and a broadcast address.
- Pattern hits: the devcontainer Dockerfile installs ClickHouse with its official curl | sh, a Codex cloud setup script waits for ports using bash's /dev/tcp (flagged as a raw socket, but it only checks whether a service is up), and two very long lines are recorded trace fixtures.
- We read the telemetry module. Self-hosted Langfuse sends PostHog a periodic count of projects, traces, observations, scores and dataset items with an instance identifier, and never trace contents or prompts. docker-compose.yml marks every default credential CHANGEME (NEXTAUTH_SECRET mysecret, an all-zero ENCRYPTION_KEY, minio and Redis passwords) and publishes the web UI on 3000 and MinIO on 9090 to all interfaces, while the databases stay on localhost.
- pnpm-lock.yaml pins 2,418 packages with nine known advisories (3 high, 3 moderate, 3 low), all denial-of-service or build-time issues in basic-ftp, braces, deepmerge-ts, uuid, webpack and the AI SDK. The two Rust lockfiles, 404 crates for the AI gateway and native module, are clean. Install hooks enforce pnpm, run a repository helper and set up husky; a Rust build script compiles the native package.
- 36 workflows. Three were flagged for pull_request_target: two labelling workflows with no PR checkout, and preview-build.yml, which actually runs on pull_request, builds only same-repository PRs, and uses AWS credentials scoped so that a pull_request_target run could not assume them; the scanner matched its explanatory comment. All 67 third-party actions are pinned to commits. Security policy, Dependabot, CodeQL, licence and contributing guide present.
What the scanner counted
| Check | Result |
|---|---|
| Secrets | 23 candidates found and read; see the notes above. |
| Suspicious code | 4 pattern hits found and read; every one is listed under the raw findings. |
| Install-time code | 3 npm lifecycle scripts. 1 Cargo build script. 9 installer scripts (one can call sudo) |
| Committed binaries | None. |
| CI workflows | 36 workflows. 3 use pull_request_target, 1 of which check out the pull request head. 0 of 67 third-party actions pinned to a tag rather than a commit. |
| Network hosts | 40 distinct hosts referenced from source; most often langfuse.com, cloud.langfuse.com, github.com, api.openai.com. 8 URLs to a bare IP address, listed under the raw findings. |
| Known vulnerabilities | 9 advisories across 2,721 pinned packages: 0 critical, 3 high, 3 moderate, 3 low. ai-gateway/Cargo.lock: 229 packages, 0 advisories; packages/native/Cargo.lock: 175 packages, 0 advisories; pnpm-lock.yaml: 2,418 packages, 9 advisories. |
| Project hygiene | Has security policy, automated dependency updates, CodeQL, licence file, contributing guide. |
| OpenSSF Scorecard | Not scored: the project is not in Scorecard's weekly index. |
The raw findings
Every hit the scanner wrote out, with a link to the exact line at the scanned commit. Secrets candidates are redacted.
Secret candidates (23, redacted)
Pattern hits (4)
| Where | Rule | Match |
|---|---|---|
| .devcontainer/Dockerfile:26 | download-piped-to-shell | RUN curl https://clickhouse.com/ | sh && \ |
| packages/shared/src/utils/normalized-io/conventions/providers/agno/fixtures.ts:34 | very-long-line | 5799 chars |
| scripts/codex/cloud_services.sh:294 | raw-socket-shell | until (echo >"/dev/tcp/$host/$port") >/dev/null 2>&1; do |
| web/src/__tests__/server/otel-api.servertest.ts:346 | very-long-line | 8846 chars |
URLs to bare IP addresses (8)
| Where | Rule | Match |
|---|---|---|
| web/src/__tests__/server/llm-connections-api.servertest.ts:22 | ip-literal-url | const TEST_PUBLIC_LLM_BASE_URL = "https://1.1.1.1/v1"; |
| web/src/__tests__/server/llm-connections-api.servertest.ts:23 | ip-literal-url | const TEST_UPDATED_PUBLIC_LLM_BASE_URL = "https://1.1.1.1/v2"; |
| web/src/__tests__/server/llm-connections-api.servertest.ts:24 | ip-literal-url | const TEST_CUSTOM_PUBLIC_LLM_BASE_URL = "https://1.1.1.1/custom/v1"; |
| web/src/__tests__/server/llm-connections-api.servertest.ts:25 | ip-literal-url | const TEST_SCHEMA_PUBLIC_LLM_BASE_URL = "https://1.1.1.1/schema/v1"; |
| worker/src/__tests__/llm-base-url-validation.test.ts:135 | ip-literal-url | validateLlmConnectionBaseURL("https://1.1.1.1/v1"), |
| worker/src/__tests__/llm-base-url-validation.test.ts:179 | ip-literal-url | validateLlmConnectionBaseURL("http://1.1.1.1/v1"), |
| worker/src/__tests__/webhook-validation.test.ts:134 | ip-literal-url | await expect(validateWebhookURL("http://224.0.0.1/hook")).rejects.toThrow( |
| worker/src/__tests__/webhook-validation.test.ts:142 | ip-literal-url | validateWebhookURL("http://255.255.255.255/hook"), |
npm lifecycle scripts (3)
package.jsonpreinstall:node -e "if (!process.env.npm_config_user_agent?.startsWith('pnpm/')) { console.error('This repository uses pnpm. Run pnpm install.'); process.exit(1); }"package.jsonpostinstall:node -e "const fs = require('node:fs'); const cp = require('node:child_process'); if (!fs.existsSync('scripts/postinstall.sh')) { console.log('Skipping repo postinstall helper: scripts/postinstall.sh …package.jsonprepare:husky
Installer scripts (9)
- ai-gateway/scripts/run-dev.sh, 21 lines
- scripts/agents/setup-cursor-cloud.sh, 21 lines, uses sudo
- scripts/agents/setup.sh, 49 lines
- scripts/agents/start-cursor-cloud.sh, 129 lines, uses sudo
- scripts/agents/start-cursor-cloud.test.sh, 115 lines, uses sudo; talks to external.example
- scripts/ci/install-playwright.sh, 33 lines, uses sudo; talks to mirror.pilotfiber.com, mirror.tzulo.com
- scripts/codex/setup.sh, 8 lines
- scripts/codex/setup.test.sh, 126 lines
- scripts/codex/setup_cloud.sh, 49 lines
Worst known vulnerabilities (9 of 9)
| Advisory | Severity | Package | Summary |
|---|---|---|---|
| GHSA-c475-qrg2-pj4r | high | basic-ftp@5.3.1 | basic-ftp: Quadratic-time CPU denial of service in Client.list() Unix directory-listing parser (RE_LINE backtracking) |
| GHSA-vfj7-8cjw-p6xm | high | braces@3.0.3 | braces vulnerable to stack-exhaustion denial of service through deeply nested patterns |
| GHSA-ggr8-5vv4-36mx | high | deepmerge-ts@7.1.5 | DeepmergeTS has stack exhaustion when merging recursive object graphs |
| GHSA-w5hq-g745-h8pq | moderate | uuid@10.0.0 | uuid: Missing buffer bounds check in v3/v5/v6 when buf is provided |
| GHSA-w5hq-g745-h8pq | moderate | uuid@8.3.2 | uuid: Missing buffer bounds check in v3/v5/v6 when buf is provided |
| GHSA-w5hq-g745-h8pq | moderate | uuid@9.0.1 | uuid: Missing buffer bounds check in v3/v5/v6 when buf is provided |
| GHSA-866g-f22w-33x8 | low | @ai-sdk/provider-utils@2.2.8 | @ai-sdk/provider-utils has an Uncontrolled Resource Consumption issue |
| GHSA-38r7-794h-5758 | low | webpack@5.97.1 | webpack buildHttp HttpUriPlugin allowedUris bypass via HTTP redirects → SSRF + cache persistence |
| GHSA-8fgc-7cc6-rx7x | low | webpack@5.97.1 | webpack buildHttp: allowedUris allow-list bypass via URL userinfo (@) leading to build-time SSRF behavior |
Workflows worth a look
- .github/workflows/label-cursor-prs.yml: pull_request_target
- .github/workflows/preview-autolabel.yml: pull_request_target
- .github/workflows/preview-build.yml: pull_request_target, checks out the PR head
By the numbers
| Stars | 35.3K |
|---|---|
| Forks | 3,911 |
| Contributors | 217 |
| Commits | 9,739 |
| Open issues | 323 |
| Open pull requests | 678 |
| Releases | 705 |
| Latest release | v4.50.0 |
| Licence | custom |
| Main language | TypeScript |
| Project age | 3 years |
| Last push | Oct 2, 2026 |
| Tracked files | 6,525 |
| Lines of code | 1.3M |
| Checkout size | 50 MB |
Lines by language: TypeScript 1.1M, JSON 67.2K, Markdown 44.6K, YAML 38.8K, Rust 15.3K, JavaScript 11.2K.
Questions
Is Langfuse free?
Self-hosting is free: everything outside the ee folders is MIT licensed, and some enterprise features in those folders need a licence key. Langfuse Cloud has a free tier that needs no credit card, with paid plans above it.
Does Langfuse only work with OpenAI?
No. The Python and JavaScript SDKs trace any code you wrap, and there are integrations for Amazon Bedrock, Ollama, LangChain, LlamaIndex, LiteLLM, the Vercel AI SDK, CrewAI and many more, plus a public API with an OpenAPI spec.
Should I use Langfuse or promptfoo?
They do different jobs. promptfoo tests prompts and models from the command line before you ship. Langfuse watches the application after it ships, recording real traffic and scoring it. Plenty of teams use both, and Langfuse lists an integration with promptfoo.
This post is part of GitHub Tools, where every repository is cloned and scanned before it is written up. The scan is a snapshot of one commit on one day; the repository has moved on since, so check it before you install.
