Referencja API
Adres bazowy: https://fansuby.cc/api/v1. Odpowiedzi to JSON w UTF-8, daty w ISO 8601 (UTC), CORS jest włączony.
- Wersja v1
- Tylko odczyt
- 120 zapytań na minutę
Klucz API
Każde zapytanie (poza openapi.json i /api/health) wymaga klucza w jednym z nagłówków. W przeglądarce, w której jesteś zalogowany, klucz nie jest potrzebny.
Authorization: Bearer fsb_…
# albo
X-Api-Key: fsb_…Do pięciu kluczy na konto, zarządzasz nimi w ustawieniach konta. Klucz działa jak hasło tylko do odczytu: nie wrzucaj go do repozytorium ani do kodu, który zobaczą inni.
Limity
- Zapytania API
- 120 na minutę na konto, wspólnie dla wszystkich kluczy. Stan limitu podają nagłówki
X-RateLimit-Limit,X-RateLimit-RemainingiX-RateLimit-Reset(koniec okna, Unix w sekundach). - Pobieranie plików
- Bez dziennego limitu, z przerwą przeciw masowemu ściąganiu: 30 plików na minutę, dla zaufanych tłumaczy 60.
- Po przekroczeniu
- Dostajesz
429i nagłówekRetry-Afterz liczbą sekund do odczekania. - Pamięć podręczna
- Odpowiedzi z kluczem mają
Cache-Control: private. Wyniki zmieniają się rzadko, więc zapisuj je u siebie na kilka minut.
Paginacja
Listy zwracają data i pagination. Kolejne strony pobierasz parametrami page i limit (maksymalnie 100).
{
"data": [ … ],
"pagination": { "page": 1, "limit": 20, "total": 143, "totalPages": 8 }
}Błędy
Każdy błąd ma ten sam kształt, a komunikat jest po polsku. Kod w polu code nadaje się do obsługi w programie.
{ "error": { "code": "unauthorized", "message": "API wymaga konta. …" } }- 400 invalid_parameter
- Zły parametr. Pole details wskazuje który i dlaczego.
- 401 unauthorized
- Brak klucza, klucz błędny albo usunięty. Konto zbanowane też dostaje 401.
- 404 not_found
- Nie ma takiej serii, napisów lub wersji, albo napisy są ukryte.
- 429 rate_limited
- Za dużo zapytań. Poczekaj tyle, ile mówi Retry-After.
- 500 internal_error
- Błąd po naszej stronie. Spróbuj ponownie za chwilę.
- 503 search_unavailable
- Wyszukiwarka chwilowo nie działa. Dotyczy tylko /series z frazą q.
Endpointy
Wszystkie to GET. Każdy ma przykład do skopiowania, który zakłada klucz w zmiennej FANSUBY_KEY.
- /api/v1/matchNapisy do pliku wideo
- /api/v1/match/downloadPobierz najlepiej pasujące napisy
- /api/v1/seriesWyszukiwanie serii
- /api/v1/series/{id}Szczegóły serii
- /api/v1/series/{id}/episodesOdcinki serii
- /api/v1/subtitlesLista napisów
- /api/v1/subtitles/{id}Szczegóły napisów
- /api/v1/subtitles/{id}/downloadPobranie pliku napisów
GET/api/v1/match
Jedno wywołanie zamiast szukania serii, listy napisów i wyboru. Z nazwy pliku odczytuje serię, odcinek, grupę i rozdzielczość, a napisy zwraca od najlepiej pasujących. Pierwszy element data to najlepszy wybór, a score pokazuje punktację.
Parametry
- filenametekstwymagany
- Nazwa pliku wideo, np. [SubsPlease] Frieren - 05 (1080p).mkv.
- anilistId, malId, seriesIdliczba
- Wskazują serię wprost, bez szukania po tytule. Wystarczy jeden.
- episodeliczba
- Nadpisuje numer odcinka odczytany z nazwy.
- durationms
- Długość wideo w milisekundach. Poprawia dobór napisów.
- formatass | srt
- Preferowany format przy remisie (domyślnie ass).
- langtekst
- Kod języka.
Przykład
curl -G -H "Authorization: Bearer $FANSUBY_KEY" \
--data-urlencode "filename=Frieren - 05.mkv" \
https://fansuby.cc/api/v1/matchZwraca: Obiekt z match (seria, odcinek, odczytane pola) i data (napisy z polem score). Pusta data oznacza, że serii nie brakuje, ale nie ma jeszcze napisów do odcinka. 404, gdy nie znaleziono serii.
GET/api/v1/match/download
Te same parametry co /match. Zamiast JSON-a przekierowuje (302) do pliku najlepszych napisów.
Przykład
curl -L -OJ -G -H "Authorization: Bearer $FANSUBY_KEY" \
--data-urlencode "filename=Frieren - 05.mkv" \
https://fansuby.cc/api/v1/match/downloadZwraca: 302 z nagłówkiem Location albo 404, gdy nic nie pasuje.
GET/api/v1/series
Szuka po tytułach (romaji, angielskim, japońskim i synonimach). Bez q zwraca najpopularniejsze serie.
Parametry
- qtekst
- Fraza wyszukiwania, do 200 znaków.
- adult1 | 0
- 1 dodaje serie dla dorosłych, domyślnie są ukryte.
- pageliczba
- Numer strony, od 1.
- limitliczba
- Wyników na stronę, od 1 do 100 (domyślnie 20).
Przykład
curl -H "Authorization: Bearer $FANSUBY_KEY" "https://fansuby.cc/api/v1/series?q=frieren"Zwraca: Lista data z podsumowaniami serii i obiekt pagination. 503, gdy wyszukiwarka chwilowo nie działa.
GET/api/v1/series/{id}
Pełne dane serii: opisy, gatunki, studia, następny odcinek, powiązane serie i linki.
Parametry
- idtekstwymagany
- Nasz identyfikator,
anilist:154587albomal:52991.
Przykład
curl -H "Authorization: Bearer $FANSUBY_KEY" https://fansuby.cc/api/v1/series/anilist:154587Zwraca: Obiekt data z polami serii opisanymi niżej.
GET/api/v1/series/{id}/episodes
Odcinki z liczbą dostępnych napisów. Domyślnie 100 na stronę.
Parametry
- idtekstwymagany
- Nasz identyfikator,
anilist:154587albomal:52991. - pageliczba
- Numer strony, od 1.
- limitliczba
- Wyników na stronę, od 1 do 100 (domyślnie 20).
Przykład
curl -H "Authorization: Bearer $FANSUBY_KEY" https://fansuby.cc/api/v1/series/mal:52991/episodesZwraca: Lista data z odcinkami i pagination.
GET/api/v1/subtitles
Opublikowane napisy (bieżące wersje) z filtrami. Najczęściej: wszystkie napisy do jednego odcinka. Bez filtra serii zwraca najnowsze.
Parametry
- anilistId, malId, seriesIdliczba
- Seria. Wystarczy jeden.
- episodeliczba
- Numer odcinka, np. 5 albo 12.5.
- langtekst
- Kod języka (obecnie pl).
- formatass | srt
- Format pliku.
- resolutiontekst
- 480p, 576p, 720p, 1080p lub 2160p.
- sourcetekst
- WEB-DL, WEBRip, BD, BDRip, TV, DVD lub OTHER.
- grouptekst
- Grupa wydania (np. SubsPlease, bez względu na wielkość liter) albo slug grupy tłumaczy.
- sinceISO 8601
- Tylko napisy dodane lub zmienione od tej chwili, od najnowszych. Do synchronizacji bez pobierania wszystkiego.
- adult1 | 0
- Bez filtra serii: uwzględnia serie dla dorosłych.
- pageliczba
- Numer strony, od 1.
- limitliczba
- Wyników na stronę, od 1 do 100 (domyślnie 20).
Przykład
curl -H "Authorization: Bearer $FANSUBY_KEY" \
"https://fansuby.cc/api/v1/subtitles?anilistId=154587&episode=1&resolution=1080p"Zwraca: Lista data z napisami i pagination.
GET/api/v1/subtitles/{id}
Wydanie, ekipa, sumy kontrolne i historia wersji z listą zmian (pole versions).
Parametry
- idliczbawymagany
- Identyfikator napisów.
Przykład
curl -H "Authorization: Bearer $FANSUBY_KEY" https://fansuby.cc/api/v1/subtitles/42Zwraca: Obiekt data z polami napisów i versions.
GET/api/v1/subtitles/{id}/download
Przekierowuje (302) do pliku. Domyślnie bieżąca wersja.
Parametry
- idliczbawymagany
- Identyfikator napisów.
- vliczba
- Numer wersji, jeśli chcesz starszą.
Przykład
curl -L -OJ -H "Authorization: Bearer $FANSUBY_KEY" https://fansuby.cc/api/v1/subtitles/42/downloadZwraca: 302 z nagłówkiem Location albo 404, gdy nie ma napisów lub wersji.
Pola odpowiedzi
Wszystkie adresy są bezwzględne i prowadzą do fansuby.cc. Pola, których nie ma w danych, mają wartość null.
Seria
- id, anilistId, malId, slug
- Identyfikatory. malId bywa null.
- title
- Obiekt z romaji, english i native.
- format, status, season, seasonYear
- Wartości z AniList, np. TV, RELEASING, FALL, 2026.
- episodesTotal
- Zapowiedziana liczba odcinków, jeśli jest znana.
- coverImage, coverImageMedium
- Okładki w WebP (460×650 i 230×325). Hostujemy je sami, np.
https://fansuby.cc/media/series/8/cover-3fa9….webp. Nazwa pliku zawiera skrót zawartości, więc adres się nie zmienia, dopóki obraz jest ten sam. - bannerImage
- Baner w WebP (1800×450), jeśli seria go ma.
- coverColor
- Dominujący kolor okładki jako #rrggbb. Przydaje się do tła albo akcentu.
- subtitleCount
- Liczba opublikowanych napisów.
- isAdult, url
- Oznaczenie 18+ i adres strony serii.
Szczegóły serii (/series/{id}) dodają:
- description
- Oryginalny opis po angielsku, z AniList.
- descriptionPl
- Automatyczne tłumaczenie opisu na polski. Null, gdy go jeszcze nie ma albo opis się zmienił i czeka na nowe.
- synonyms, genres, studios
- Listy tekstów.
- startDate, endDate, episodeDurationMin
- Daty (YYYY-MM-DD) i długość odcinka w minutach.
- episodeCount
- Liczba odcinków w naszym katalogu.
- averageScore, popularity
- Ocena 0 do 100 i popularność z AniList.
- nextAiringEpisode
- Numer i czas (airingAt) najbliższego odcinka albo null.
- relations
- Powiązane serie: relationType, tytuł, seriesId i url, gdy jest w naszym katalogu.
- links
- Adresy anilist, mal i rss (kanał napisów serii).
Odcinek
- id, number
- Numer jest liczbą, więc zmieści też 12.5.
- title
- Obiekt z english, romaji i japanese.
- airedAt
- Data emisji albo null.
- isFiller, isRecap
- Oznaczenia odcinków specjalnych.
- subtitleCount, url
- Liczba napisów i adres strony odcinka.
Napisy
- id, url, downloadUrl
- Identyfikator, strona dla ludzi i bezpośredni adres pliku bieżącej wersji.
- language, format
- Język (pl) oraz ass albo srt.
- releaseGroup, releaseSource, resolution
- Do jakiego wydania wideo pasują, np. SubsPlease, WEB-DL, 1080p.
- releaseFilename, alsoCompatible
- Nazwa pliku wideo i inne wydania z pasującym timingiem.
- videoDurationMs
- Długość wideo, do którego zrobiono napisy.
- version, sha256, sizeBytes
- Numer bieżącej wersji, suma kontrolna i rozmiar pliku.
- hasTypesetting, hasKaraoke, fonts
- Czy plik ma typesetting i karaoke oraz jakich czcionek używa.
- credits
- Ekipa: role (translation, proofreading, typesetting, timing, editing, karaoke), nazwa i username.
- group, uploader
- Grupa tłumaczy i osoba, która wgrała napisy. Mogą być null.
- series, episode
- Skrót serii i odcinka, do którego należą.
- downloadCount, notes
- Liczba pobrań i uwagi tłumacza.
- createdAt, updatedAt, versionCreatedAt
- Daty dodania, zmiany i wydania bieżącej wersji.
/subtitles/{id} dodaje versions: numer, listę zmian, sumę kontrolną, rozmiar, liczbę linii i adres pobrania każdej wersji.
Kanały RSS i stan serwisu
Do śledzenia nowości nie odpytuj API w pętli. Kanały RSS nie wymagają klucza:
- /rss
- Najnowsze napisy z całego serwisu.
- /seria/{slug}/rss
- Napisy do jednej serii. Adres jest też w polu links.rss.
- /grupa/{slug}/rss
- Napisy jednej grupy tłumaczy.
- /tlumacz/{username}/rss
- Napisy jednego tłumacza. Działa też pod /uzytkownik/{username}/rss.
- /api/health
- Stan serwisu dla monitoringu: 200, gdy baza, wyszukiwarka i magazyn plików działają, inaczej 503. Bez klucza.
Specyfikacja OpenAPI
Pełny opis w formacie OpenAPI 3.1 jest pod /api/v1/openapi.json i działa bez klucza. Wczytasz go do Postmana albo generatora klientów dla swojego języka.
Dobre praktyki
- Szukaj serii po AniList lub MAL ID, nie po tytule. Tytuły się różnią, ID nie.
- Do jednego pliku wideo użyj /match. Zastępuje trzy osobne zapytania.
- Do synchronizacji używaj parametru since zamiast pobierania całej listy za każdym razem.
- Zapisuj odpowiedzi na kilka minut. Lista napisów do odcinka zmienia się rzadko.
- Po 429 czekaj tyle, ile mówi Retry-After, zamiast ponawiać od razu.
- Pokazuj autorów (pole credits) i link do strony napisów. To ich praca.