# Streamlit error tracking with BugTape

`pip install bugtape` reports Streamlit page errors from the Python process. Messages are redacted by pattern. Repeats group into one issue. You can then connect MCP so an agent opens a pull request a human reviews.

The full reference is [Python](/docs/python/). This page is the Streamlit path. A checklist post is [Python and Streamlit ERROR logs](/blog/python-streamlit-bugtape-error-logs/).

## Why Streamlit page errors are awkward

Streamlit catches page errors and shows them in the app. They do not reach Python's normal uncaught-exception hook. People have described the friction of forwarding those errors to Sentry on the [Streamlit forum](https://discuss.streamlit.io/t/catch-errors-and-send-to-sentry/13819) and in [sentry-python issue 3017](https://github.com/getsentry/sentry-python/issues/3017). Streamlit also documents [`st.App(on_script_error=…)`](https://docs.streamlit.io/develop/api-reference/server/st.app) when you want to write the handler yourself.

BugTape wraps the function Streamlit calls for those errors when Streamlit is imported. The app still shows the error. BugTape files one report with the page name and the Streamlit session, and it skips Streamlit's duplicate log of the same error.

If you already run Sentry, keep it. [BugTape vs Sentry](/vs/sentry/).

## Install and start

```bash
pip install bugtape
```

The package on PyPI has no dependencies and supports Python 3.9 and later. The same reviewed wheel is `pip install https://app.bugtape.ai/sdk/python/bugtape-0.1.1-py3-none-any.whl`.

```python
import streamlit as st
import bugtape

bugtape.init(service="analytics")

st.title("Revenue")
```

Set `BUGTAPE_KEY` to a capture key from Setup → Python (`bt_live_…` or `bt_test_…`). Without a key, `init` logs one warning and reporting stays off. Streamlit reruns the page on each interaction. A second `init` with the same settings keeps the running client.

If a future Streamlit release moves that hook, `init(streamlit=True)` logs a warning. You can wrap the page yourself:

```python
from bugtape.integrations.streamlit import capture

with capture():
    render_page()
```

Check delivery with the one-liner from the docs:

```bash
BUGTAPE_KEY=bt_test_… python -c "import bugtape; bugtape.init(service='check'); bugtape.capture_message('BugTape Python check'); bugtape.flush()"
```

## What leaves the server

| Sent | Never sent |
|---|---|
| Exception type and a redacted message | Frame locals |
| File, function and line of each frame | Source lines |
| `service`, `release`, `environment` | Arguments passed to a log call |
| The log template, such as `export failed for %s` | Request bodies |

Redaction covers quoted values, numbers, emails, SQL, and ids. An f-string such as `ValueError(f"no rate for client {name}")` is finished text before BugTape sees it, so the name can remain. For that code, pass log arguments, add `extra_redactions`, use `before_send`, or set `send_messages=False`. The patterns are in [Python](/docs/python/).

Server reports have no browser DOM replay. DOM replay is a browser SDK feature, and it is not a screen video.

## Release, so a fix can be checked

Pass `release`, or set `BUGTAPE_RELEASE` or `DD_VERSION`. If those are empty, the SDK reads the first set CI commit variable, including `GITHUB_SHA` and `VERCEL_GIT_COMMIT_SHA`. The full list is `bugtape.COMMIT_ENV_KEYS` in the Python doc. A report with no release is stored as `release_missing`, and the release check cannot anchor.

## Datadog, if you already have it

When `ddtrace` is already running, the report carries the active trace and span ids. BugTape does not start Datadog. [Use BugTape with Datadog](/docs/datadog/) · [Keep Datadog, add the agent loop](/docs/beat-datadog-agent-loop/).

## Hand the issue to an agent

BugTape is not an APM product and it is not LLM observability, even when the Streamlit app calls a model. After the first error is in the inbox, connect MCP:

- [Install in Claude Code](/install/claude-code/)
- [Connect Cursor](/connect/cursor/)
- [MCP install](/docs/mcp-install/)

[Start free](/console/register?utm_source=bugtape_seo&utm_campaign=streamlit-error-tracking) and open Setup → Python. Where the data lives, and what redaction does not promise, is on [Trust](/trust/).

Your team reviews the PR. Agents do not silent-ship.
