songfinderdev
Identify any song from a link or an audio file, then read its BPM, musical key and Camelot code — from your terminal or your Python code.
The official Python client for Song Finder, a free online song finder that identifies music from a file, a microphone recording or a link. No API key. No account. No rate card.
Standard library only — no requests, no transitive dependencies, nothing to audit.
Install
pip install songfinderdev
Python 3.9+.
Why not
songfinder? An unrelated project already owns that name on PyPI, and its wheel's top-level directory issongfindertoo — sharing either name would have the two installs silently overwrite each other.songfinder-cliis not an option either: PyPI's similarity check strips common suffixes likecli,apiandsdkbefore comparing, so every such variant collides as well. Hencesongfinderdev, matching the domain.
The command installs as both songfinder and songfinderdev, so it still works if something else on your PATH already claims the shorter name.
Command line
songfinder identify "https://www.youtube.com/watch?v=..."
songfinder analyze "strobe deadmau5"
I Remember (Strobelight Edit) — deadmau5
Strobelite Seduction (2013)
ISRC: USUS10800096
Tempo: 128 BPM
Key: B Minor (Camelot 10A, Open Key 3m)
Mixes with: 10B, 9A, 11A
Energy: 59%
Danceability: 66%
(Real output, not a mock-up.)
songfinder identify <url|file> [--start SECONDS]
songfinder search <query>
songfinder analyze <query|ISRC>
songfinder similar <query|ISRC> [--limit N] [--harmonic]
Every command that names a track accepts a search phrase as readily as an ISRC — you never have to look a code up by hand first. Add --json to any command for the raw API response.
# what is playing in this video
songfinder identify "https://www.tiktok.com/@user/video/123..."
# what is this file on disk
songfinder identify ~/Music/unknown.mp3
# sample 90 seconds in, when the opening is silence or an intro
songfinder identify "https://youtu.be/..." --start 90
# five tracks that mix harmonically into this one
songfinder similar "strobe deadmau5" --harmonic --limit 5
Library
from songfinderdev import SongFinder, tempo_disagrees
sf = SongFinder()
track = sf.search("blinding lights weeknd")[0]
detail = sf.detail(track["isrc"])
print(detail["features"]["tempo"]) # 171.005
print(detail["features"]["key"]["camelot"]) # '3B'
print(detail["features"]["key"]["compatible"]) # ['3A', '2B', '4B']
if tempo_disagrees(detail):
# a second provider read this at half or double time — see below
...
| Method | Returns |
|---|---|
search(query) |
Up to 10 catalogue candidates with ISRCs |
detail(isrc) |
Tempo, key, Camelot code, energy/danceability/valence, genre |
similar(isrc, limit=…, harmonic=…) |
Neighbouring tracks, each with its own tempo and key |
identify_url(url, start_seconds=None) |
Recognition from a page or media URL |
identify_file(path) |
Recognition from a local audio file (max 10MB) |
resolve_isrc(title, artist) |
Bridges recognition output to the analysis methods |
Failures raise SongFinderError, which carries the HTTP status when there was one.
Two things this gets right
Half-time and double-time tempo. detail() returns a second provider's reading in tempoCrossCheck. When the two disagree by more than 3 BPM, one of them counted the groove at half speed — an 87/174 pair is the same track. tempo_disagrees(detail) tells you; the CLI prints a warning. Reporting the primary figure alone is how this data most often misleads people.
Recognition returns no ISRC. Every analysis method is keyed by ISRC, so the chain would dead-end right after the interesting part. resolve_isrc() closes that gap with one catalogue search, and never raises — a lookup failure must not sink a successful match.
Notes
Recognition is rate-limited per IP because it spends paid third-party quota. The analysis endpoints allow roughly one call per 1–5 seconds depending on how far they fan out upstream. A 429 means you went too fast, not that the track is missing.
The credited artist is not always the original artist. Widely re-uploaded tracks match white-label catalogue entries, so a famous song can come back credited to a label nobody has heard of. The title is still right — search that title to find the original release.
Audio you identify is uploaded to songfinder.dev and is not retained. Analysis calls send only a text query or an ISRC — no audio.
Coverage is uneven for long-tail releases. Many have a tempo but no key, or no analysis at all. Missing fields come back None rather than being invented.
Also available
- songfinder — the same client and CLI for Node.js
- songfinder-mcp — MCP server for Claude, Cursor, Windsurf and Zed
- songfinder-skills — Agent Skills, installable with
npx skills add - songfinder.dev — the web app, plus BPM & key detection, a similar-songs finder and more
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file songfinderdev-0.1.0.tar.gz.
File metadata
- Download URL: songfinderdev-0.1.0.tar.gz
- Upload date:
- Size: 11.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bcbdae251bd13d918b4226fd5f09ec1a98b026a3c4c3f54cc314fa44325063d7
|
|
| MD5 |
6b49a160ee296dfce571cc9ee8ed9511
|
|
| BLAKE2b-256 |
c1e5b31c88b50b0952871ddec7f9d58782e1f6d31885ae84f2e9099dc3779224
|
Provenance
The following attestation bundles were made for songfinderdev-0.1.0.tar.gz:
Publisher:
publish-pypi.yml on songfinder-dev/songfinder
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
songfinderdev-0.1.0.tar.gz -
Subject digest:
bcbdae251bd13d918b4226fd5f09ec1a98b026a3c4c3f54cc314fa44325063d7 - Sigstore transparency entry: 2475575000
- Sigstore integration time:
-
Permalink:
songfinder-dev/songfinder@92847de05196c15bc7c0f300bffab56783228d5c -
Branch / Tag:
refs/heads/main - Owner: https://github.com/songfinder-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@92847de05196c15bc7c0f300bffab56783228d5c -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file songfinderdev-0.1.0-py3-none-any.whl.
File metadata
- Download URL: songfinderdev-0.1.0-py3-none-any.whl
- Upload date:
- Size: 13.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
961879a7cefde6d347d5ed6e0dc3412253730307c36c35a034e559f66cf0cc3b
|
|
| MD5 |
f2cb69f0830ba1683a6d9c68d255d551
|
|
| BLAKE2b-256 |
dd6f2b923b8a90c73e4e025b9b46459849c8850f6cc5805a6337545b344e1825
|
Provenance
The following attestation bundles were made for songfinderdev-0.1.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on songfinder-dev/songfinder
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
songfinderdev-0.1.0-py3-none-any.whl -
Subject digest:
961879a7cefde6d347d5ed6e0dc3412253730307c36c35a034e559f66cf0cc3b - Sigstore transparency entry: 2475575010
- Sigstore integration time:
-
Permalink:
songfinder-dev/songfinder@92847de05196c15bc7c0f300bffab56783228d5c -
Branch / Tag:
refs/heads/main - Owner: https://github.com/songfinder-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@92847de05196c15bc7c0f300bffab56783228d5c -
Trigger Event:
workflow_dispatch
-
Statement type: