Singer SDK
raw JSON → 0.53.6 verified Tue May 12 auth: no python install: verified
The Singer SDK (Software Development Kit) is a Python framework for building Singer taps (data extractors) and targets (data loaders). It simplifies the creation of data connectors that are compliant with the open-source Singer Spec, handling much of the boilerplate code for configuration, schema discovery, state management, and data serialization. The library is actively maintained by Meltano and the Singer community, with frequent releases addressing bug fixes, new features, and deprecations.
pip install singer-sdk Warnings
breaking SQL-related classes (e.g., `SQLTap`, `SQLStream`, `SQLSink`, `SQLConnector`, `SQLTarget`) will be moved from top-level `singer_sdk` imports to `singer_sdk.sql`. ↓
fix Update your imports from `from singer_sdk import SQLTap` to `from singer_sdk.sql import SQLTap`.
breaking The functions `singer_sdk.testing.get_standard_tap_tests` and `singer_sdk.testing.get_standard_target_tests` will be removed. They are replaced by `singer_sdk.testing.get_tap_test_class` and `singer_sdk.testing.get_target_test_class` to generate richer test suites. ↓
fix Migrate your testing setup to use the new `get_tap_test_class` and `get_target_test_class` functions.
breaking The `PyJWT` and `cryptography` libraries for JWT authentication, and `SQLAlchemy` for SQL connectors, will no longer be installed by default. They will become optional extra dependencies. ↓
fix If using `OAuthJWTAuthenticator`, install with `pip install singer-sdk[jwt]`. If using SQL-based taps/targets, install with `pip install singer-sdk[sql]` or explicitly install `SQLAlchemy`.
deprecated The `Stream.reset_state_progress_marker` method is deprecated and its logic was never used at the stream level. ↓
fix Remove calls to `Stream.reset_state_progress_marker`. Review the SDK documentation for alternative state management patterns if needed.
gotcha Prior to v0.53.6, specific interactions with the `simpleeval` dependency could lead to issues when using `json` within stream map expressions. ↓
fix Upgrade `singer-sdk` to v0.53.6 or newer. Ensure your `simpleeval` version is compatible if you manually manage it. Review usage of `json` in stream map expressions for compatibility.
gotcha The SDK previously crashed with `SyntaxError: Unexpected end of JSON input` if an API returned an empty body with a `200` status code but without a `Content-Length: 0` header or a `204` status code. ↓
fix Upgrade to a newer version of `singer-sdk` (e.g., v0.53.5 or later) to benefit from improved JSON parsing error handling and graceful empty response management.
gotcha When using stream map expressions, `NameNotDefined` errors (e.g., `'datetime' is not defined for expression 'datetime.datetime.now()'`) can occur if the `simpleeval` context does not have the necessary built-ins or if the SDK version is too old for specific functions. ↓
fix Ensure your SDK version is up-to-date. If encountering custom functions, verify the tap explicitly adds them to the `simpleeval` context. For common functions like `datetime`, ensure your SDK version supports them or consider more explicit imports within the expression if allowed by the tap's `simpleeval` configuration (though this is less common).
Install
pip install singer-sdk[sql] pip install singer-sdk[jwt] Install compatibility verified last tested: 2026-05-12
python os / libc variant status wheel install import disk
3.10 alpine (musl) singer-sdk wheel - 1.31s 62.1M
3.10 alpine (musl) singer-sdk - - 1.31s 61.7M
3.10 alpine (musl) jwt wheel - 1.31s 78.6M
3.10 alpine (musl) jwt - - 1.31s 77.1M
3.10 alpine (musl) sql wheel - 1.28s 62.1M
3.10 alpine (musl) sql - - 1.29s 61.7M
3.10 slim (glibc) singer-sdk wheel 7.2s 0.98s 61M
3.10 slim (glibc) singer-sdk - - 0.92s 60M
3.10 slim (glibc) jwt wheel 8.0s 0.96s 77M
3.10 slim (glibc) jwt - - 0.92s 76M
3.10 slim (glibc) sql wheel 6.9s 0.94s 61M
3.10 slim (glibc) sql - - 0.93s 60M
3.11 alpine (musl) singer-sdk wheel - 1.61s 69.7M
3.11 alpine (musl) singer-sdk - - 1.75s 69.2M
3.11 alpine (musl) jwt wheel - 1.54s 86.8M
3.11 alpine (musl) jwt - - 1.74s 85.2M
3.11 alpine (musl) sql wheel - 1.61s 69.7M
3.11 alpine (musl) sql - - 1.74s 69.2M
3.11 slim (glibc) singer-sdk wheel 6.6s 1.46s 69M
3.11 slim (glibc) singer-sdk - - 1.32s 68M
3.11 slim (glibc) jwt wheel 7.2s 1.38s 86M
3.11 slim (glibc) jwt - - 1.31s 84M
3.11 slim (glibc) sql wheel 6.1s 1.39s 69M
3.11 slim (glibc) sql - - 1.33s 68M
3.12 alpine (musl) singer-sdk wheel - 1.74s 60.0M
3.12 alpine (musl) singer-sdk - - 1.77s 59.5M
3.12 alpine (musl) jwt wheel - 1.70s 77.0M
3.12 alpine (musl) jwt - - 1.75s 75.4M
3.12 alpine (musl) sql wheel - 1.68s 60.0M
3.12 alpine (musl) sql - - 1.73s 59.5M
3.12 slim (glibc) singer-sdk wheel 5.6s 1.69s 59M
3.12 slim (glibc) singer-sdk - - 1.83s 58M
3.12 slim (glibc) jwt wheel 5.9s 1.63s 76M
3.12 slim (glibc) jwt - - 1.66s 74M
3.12 slim (glibc) sql wheel 5.2s 1.67s 59M
3.12 slim (glibc) sql - - 1.66s 58M
3.13 alpine (musl) singer-sdk wheel - 1.79s 59.6M
3.13 alpine (musl) singer-sdk - - 1.74s 58.9M
3.13 alpine (musl) jwt wheel - 1.68s 76.6M
3.13 alpine (musl) jwt - - 1.75s 74.9M
3.13 alpine (musl) sql wheel - 1.67s 59.6M
3.13 alpine (musl) sql - - 1.75s 58.9M
3.13 slim (glibc) singer-sdk wheel 5.5s 1.70s 58M
3.13 slim (glibc) singer-sdk - - 1.75s 58M
3.13 slim (glibc) jwt wheel 6.1s 1.58s 75M
3.13 slim (glibc) jwt - - 1.70s 74M
3.13 slim (glibc) sql wheel 5.5s 1.64s 58M
3.13 slim (glibc) sql - - 1.73s 58M
3.9 alpine (musl) singer-sdk wheel - 1.69s 60.5M
3.9 alpine (musl) singer-sdk - - 1.61s 60.3M
3.9 alpine (musl) jwt wheel - 1.64s 77.8M
3.9 alpine (musl) jwt - - 1.60s 76.5M
3.9 alpine (musl) sql wheel - 1.66s 60.5M
3.9 alpine (musl) sql - - 1.62s 60.3M
3.9 slim (glibc) singer-sdk wheel 8.2s 1.64s 60M
3.9 slim (glibc) singer-sdk - - 1.39s 60M
3.9 slim (glibc) jwt wheel 9.2s 1.55s 77M
3.9 slim (glibc) jwt - - 1.38s 76M
3.9 slim (glibc) sql wheel 8.1s 1.54s 60M
3.9 slim (glibc) sql - - 1.39s 60M
Imports
- Tap
from singer_sdk import Tap - Stream
from singer_sdk import Stream - RESTStream
from singer_sdk.streams import RESTStream - th (typing helpers)
import singer_sdk.typing as th - SQLTap, SQLStream, SQLSink, SQLConnector, SQLTarget wrong
from singer_sdk import SQLTapcorrectfrom singer_sdk.sql import SQLTap, SQLStream, SQLSink, SQLConnector, SQLTarget
Quickstart last tested: 2026-04-24
import os
from singer_sdk import Tap, Stream
from singer_sdk.streams import RESTStream
import singer_sdk.typing as th
class UsersStream(RESTStream):
"""Users stream."""
name = "users"
url_base = os.environ.get("API_URL", "https://api.example.com")
path = "/users"
primary_keys = ["id"]
records_jsonpath = "$.data[*]"
schema = th.PropertiesList(
th.Property("id", th.IntegerType),
th.Property("name", th.StringType),
th.Property("email", th.StringType),
).to_dict()
class MyTap(Tap):
"""My custom tap."""
name = "tap-myapi"
config_jsonschema = th.PropertiesList(
th.Property("api_url", th.StringType, required=True),
th.Property("api_key", th.StringType, required=True, secret=True),
).to_dict()
def discover_streams(self):
return [UsersStream(self)]
# To run the tap (e.g., discover catalog or sync data):
# python -m your_tap_module --config config.json --discover > catalog.json
# python -m your_tap_module --config config.json --catalog catalog.json --state state.json > state_new.json
if __name__ == "__main__":
MyTap.cli()