Handleiding
1. Aan de slag
AniRena is een torrentindex gericht op anime, manga, audio en aanverwante media. Je kunt torrents bladeren en downloaden zonder account. Een account is vereist om torrents te uploaden, aan groepen deel te nemen of de API te gebruiken.
De navigatiebalk bovenaan biedt toegang tot de belangrijkste onderdelen van de site:
- Startpagina — de torrentlijst en zoekpagina.
- Uploaden — een nieuwe torrent indienen (vereist inloggen).
- Handleiding — deze pagina.
- Statistieken — sitebrede statistieken (torrents, peers, uploads over tijd).
- Groepen — directorie van release-groepen.
- RSS — RSS-feed van recente uploads, filterbaar op categorie.
Je accountmenu (rechtsboven als je bent ingelogd) opent een profielpaneel waarin je instellingen kunt aanpassen, beveiligingsopties kunt beheren en toegang hebt tot je API-sleutel.
2. Bladeren & zoeken
De startpagina toont alle torrents gesorteerd op uploaddatum. Gebruik de zoekbalk bovenaan om resultaten te filteren.
Eenvoudig zoeken
Typ woorden in de zoekbalk en druk op Enter (of klik op het zoekpictogram). Resultaten worden op relevantie gesorteerd wanneer een zoekopdracht actief is.
Zoekoperatoren
De volgende operatoren kunnen worden gecombineerd met een gewone zoekopdracht:
| Operator | Voorbeeld | Effect |
|---|---|---|
user:"name" | user:"SubsPlease" | Toon alleen torrents geupload door die gebruiker. |
Door op de naam van een uploader in de torrentlijst te klikken wordt automatisch een gebruikerszoekopdracht uitgevoerd.
Categorieen & subcategorieen
Gebruik de categorieselector (het rastericon naast de zoekbalk) om resultaten te beperken tot een categorie. Beschikbare categorieen zijn:
- Anime
- Manga/Manhwa/Comic
- Audio
- Literatuur
- Live Action
- Afbeeldingen
- Software
- Hentai
- Overig
Elke categorie heeft subcategorieen (bijv. Anime naar RAW, Sub/Audio, Muziekvideo) die in het categoriemodal kunnen worden geselecteerd.
Sorteren & filters
De kolomkoppen in de torrentlijst zijn klikbaar om op die kolom te sorteren (oplopend of aflopend). Beschikbare sorteerkolommen: datum, naam, grootte, voltooide downloads. Opmerking: seeders en leechers zijn live-waarden uit Redis en kunnen niet worden gebruikt om op te sorteren.
Taalfilter
Gebruik de taalselector (vlagicon) om alleen torrents te tonen die zijn getagd met een specifieke taal.
RSS-feed
De RSS-feed op /rss geeft de nieuwste uploads. Voeg ?category=anime (of een andere categorieslug) toe om de feed te filteren. De meeste torrentclients ondersteunen automatisch downloaden via RSS vanuit deze URL.
3. Torrents downloaden
Klik op de naam van een torrent om het detailpaneel te openen. Van daaruit kun je:
- .torrent downloaden — slaat het .torrent-bestand direct op. De directe URL is
/torrents/{id}.torrent - Magnetlink — opent direct in je torrentclient via het magnet-URI-protocol. De URL is
/torrents/{id}/magnet
Het detailpaneel toont ook de beschrijving, bestandslijst, trackerlijst en seeder/leecheraantallen van de torrent.
Oude downloadlinks
Oude AniRena-downloadlinks worden nog steeds ondersteund en worden automatisch doorgestuurd naar het juiste .torrent-bestand via het legacy-ID: /dl/{old_id}
Aanbevolen BitTorrent-clients
Elke moderne BitTorrent-client werkt. De onderstaande clients worden aanbevolen en ondersteunen BitTorrent v2 / hybride torrents volledig:
4. Een account aanmaken
Registratie
Klik op Aanmelden in de navigatiebalk. Kies een gebruikersnaam, geef een e-mailadres op en stel een wachtwoord in (minimale lengte verplicht). Je moet de sitevoorwaarden lezen en accepteren voordat je account wordt aangemaakt.
E-mailactivering
Na het aanmelden wordt een verificatie-e-mail naar je adres gestuurd. Klik op de link in de e-mail om je account te activeren. Als je deze niet hebt ontvangen, gebruik dan de link Account activeren op de inlogpagina om een nieuwe code aan te vragen.
Wachtwoord herstellen
Als je je wachtwoord vergeten bent, klik dan op Wachtwoord vergeten op de aanmeldpagina en voer je e-mailadres in. Er wordt een herstelkoppeling naar je verstuurd. De koppeling is eenmalig en verloopt na korte tijd.
5. Torrents uploaden
Ga naar Uploaden in de navigatiebalk. Je moet ingelogd zijn met een actief, niet-verbannen account. De uploadpagina heeft twee tabbladen:
Uploadtabblad — een bestaand .torrent-bestand indienen
Sleep een .torrent-bestand of selecteer er een. Vul na het laden de velden in:
| Veld | Vereist | Beschrijving |
|---|---|---|
| Torrentbestand | Ja | Het te uploaden .torrent-bestand. |
| Naam | Nee | Overschrijf de weergavenaam van de torrent. Als dit leeg wordt gelaten, wordt de naam gebruikt die in het torrentbestand is ingesloten. |
| Categorie | Ja | De inhoudscategorie (Anime, Manga, Audio, enz.). |
| Subcategorie | Nee | Een specifieker type binnen de categorie (bijv. RAW, Sub/Audio). |
| Talen | Nee | Een of meer taaltags die de inhoudstaal beschrijven. |
| Groep | Nee | Koppel deze release aan een groep waarvan je lid bent. |
| Beschrijving | Nee | Markdown-beschrijving weergegeven op de torrentdetailpagina (max. 65535 tekens). |
| Prive | Nee | Stelt de privevlag in de torrent in, waardoor DHT/PEX wordt uitgeschakeld. Handig voor alleen-tracker-torrents. |
| Announce-URL | Nee | Overschrijf of voeg de primaire tracker-announce-URL toe. |
| Extra trackers | Nee | Gelezen uit het torrentbestand. Kan niet worden gewijzigd tijdens het uploaden — gebruik het tabblad Aanmaken als je de trackerslijst wilt aanpassen. |
| Opmerking | Nee | Overschrijf het torrentcommentaarveld dat in het bestand is ingesloten. |
Je torrent moet minstens één AniRena-tracker-URL in de announce-lijst hebben (in welk tier dan ook). De site controleert dit bij het uploaden en zal torrents afwijzen die geen AniRena-tracker bevatten. Als je de torrent hebt aangemaakt zonder de AniRena-tracker toe te voegen, upload hem dan en download hem daarna opnieuw van de site — het gedownloade bestand heeft automatisch de juiste trackers.
Aanmaken-tabblad — een nieuwe torrent bouwen
Met het tabblad Aanmaken kun je een nieuw .torrent-bestand helemaal opnieuw genereren door bestandspaden, tracker-URLs en andere torrentparameters rechtstreeks in de browser op te geven. De resulterende torrent wordt ingediend met dezelfde metadatavelden als hierboven.
Moderatie
Uploads worden automatisch gecontroleerd aan de hand van een lijst met verboden inhoudspatronen (namen, bestandsnamen, beschrijvingen). Torrents die overeenkomen met een verboden patroon worden geweigerd. Dubbele torrents (zelfde info-hash) worden ook geweigerd.
6. Jouw account
Klik op je gebruikersnaam in de rechterbovenhoek om het profielpaneel te openen. Het is georganiseerd in inklapbare secties:
Instellingen
Wijzig het UI-thema, lettergrootte, kleurenschema, interfacetaal en torrentgerelateerde weergavevoorkeuren. Wijzigingen worden automatisch opgeslagen.
Wachtwoord
Voer je huidige wachtwoord en het nieuwe wachtwoord tweemaal in. Er wordt een verificatiecode naar je geregistreerde e-mailadres gestuurd die moet worden ingevoerd om de wijziging te bevestigen. Als tweefactorauthenticatie is ingeschakeld, is ook je TOTP-code vereist.
Tweefactorauthenticatie (2FA)
Schakel TOTP-gebaseerde tweefactorauthenticatie in met behulp van een authenticator-app (bijv. Google Authenticator, Aegis, Bitwarden). Bij het inschakelen van 2FA:
- Scan de QR-code (of voer het geheim handmatig in) in je authenticator-app.
- Voer de 6-cijferige code in die in je app wordt weergegeven om de instelling te bevestigen.
- Sla de weergegeven herstelcodes op — dit zijn eenmalige codes om toegang te herwinnen als je je apparaat verliest.
Om 2FA uit te schakelen, voer je je huidige TOTP-code in en bevestig je.
Actieve sessies
Bekijk alle actieve inlogsessies, inclusief browser, besturingssysteem, IP-adres en tijdstip van laatste activiteit. Klik op Intrekken bij een sessie die je niet herkent. Je kunt ook alle sessies tegelijk intrekken om op elk apparaat uit te loggen.
API-sleutel
Genereer een persoonlijke API-sleutel om torrents programmatisch te uploaden via de AniRena API. Klik op Sleutel genereren om er een aan te maken — de volledige sleutel wordt eenmalig direct na het genereren weergegeven. Bewaar hem veilig; hij wordt daarna niet meer volledig weergegeven. Gebruik Intrekken om de sleutel permanent ongeldig te maken.
Account verwijderen
Het aanvragen van accountverwijdering start een respijtperiode van 30 dagen. Je account wordt onmiddellijk uitgeschakeld en na 30 dagen permanent verwijderd. Je kunt de verwijdering op elk moment binnen die periode annuleren door in te loggen en op Verwijdering annuleren te klikken.
7. AniRena API
AniRena biedt een JSON API waarmee je torrents programmatisch kunt uploaden met een persoonlijke API-sleutel. De API past dezelfde regels toe als de webinterface: verbodcontroles, snelheidslimieten en site-modusbeperkingen zijn allemaal van toepassing. Elke API-upload wordt vastgelegd in het auditlogboek.
Authenticatie
De API gebruikt een tweetrapsauthenticatiestroom. Wissel eerst je permanente API-sleutel in voor een kortlevend bearer-token, geef dat token vervolgens door in de Authorization-header van elk API-verzoek.
Je API-sleutel is beschikbaar onder Je account > API-sleutel. Houd hem geheim — iedereen met de sleutel kan bearer-tokens verkrijgen en uploaden namens jou. Als hij gecompromitteerd is, trek hem dan onmiddellijk in en genereer een nieuwe.
Stap 1 — Verkrijg een bearer-token
/api/v1/auth/tokenStuur een POST-verzoek naar het token-endpoint met je API-sleutel in de Authorization-header. Een request-body is niet vereist.
Authorization: ApiKey <your-api-key>
Token-respons
{
"token": "<bearer-token>",
"token_type": "Bearer",
"expires_in": 3600
}Levensduur van token
Bearer-tokens blijven tot 3600 seconden geldig vanaf het moment van uitgifte en kunnen voor elke aanroep opnieuw worden gebruikt totdat ze verlopen. Wanneer een token verloopt, maak je een nieuwe via POST /api/v1/auth/token. Elke respons retourneert nog steeds het huidige token in de X-New-Token-header voor achterwaartse compatibiliteit.
X-New-Token: <next-bearer-token>
Inloggen met één verzoek (met 2FA)
/api/v1/auth/loginAuthenticeer met je gebruikersnaam of e-mailadres en wachtwoord in één verzoek en ontvang direct een bearer-token. Als je account 2FA heeft ingeschakeld, voeg dan je huidige authenticator-code toe in totp_code (of een herstelcode in recovery_code). Stel optioneel new_api_key in op true om in dezelfde respons ook een gloednieuwe permanente API-sleutel aan te maken.
Verzoekbody
{
"login": "username or email",
"password": "your-password",
"totp_code": "123456", // vereist als 2FA is ingeschakeld (6 cijfers)
"recovery_code": "", // alternatief voor totp_code
"new_api_key": false // zet op true om ook een nieuwe API-sleutel aan te maken
}Token-respons
{
"ok": true,
"token": "<bearer-token>",
"token_type": "Bearer",
"expires_in": 3600,
"api_key": "<new-api-key>" // alleen aanwezig wanneer new_api_key true was
}Het bearer-token werkt precies zoals een token van /api/v1/auth/token. Het veld api_key wordt alleen geretourneerd wanneer new_api_key true is — sla het direct op, want het wordt maar één keer getoond en vervangt elke vorige sleutel.
Voorbeeld — inloggen en (optioneel) een nieuwe API-sleutel ophalen
# pip install requests import requests BASE_URL = "https://www.anirena.com" # One request: authenticate (with 2FA if enabled) and get a bearer token. # Set new_api_key=True to also receive a brand-new permanent API key. resp = requests.post( f"{BASE_URL}/api/v1/auth/login", json={ "login": "your-username", # username or email "password": "your-password", "totp_code": "123456", # omit if 2FA is not enabled "new_api_key": True, # optional }, ) resp.raise_for_status() data = resp.json() token = data["token"] # use as: Authorization: Bearer <token> if "api_key" in data: print("New API key — store it now:", data["api_key"])
// Built-in fetch — requires Node.js 18+ const BASE_URL = "https://www.anirena.com"; // One request: authenticate (with 2FA if enabled) and get a bearer token. // Set new_api_key:true to also receive a brand-new permanent API key. const resp = await fetch(`${BASE_URL}/api/v1/auth/login`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ login: "your-username", // username or email password: "your-password", totp_code: "123456", // omit if 2FA is not enabled new_api_key: true, // optional }), }); const data = await resp.json(); const token = data.token; // use as: Authorization: Bearer <token> if (data.api_key) console.log("New API key — store it now:", data.api_key);
// Requires: curl extension (enabled by default in PHP 8+) <?php define("BASE_URL", "https://www.anirena.com"); // One request: authenticate (with 2FA if enabled) and get a bearer token. // Set new_api_key => true to also receive a brand-new permanent API key. $ch = curl_init(BASE_URL . "/api/v1/auth/login"); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode([ "login" => "your-username", // username or email "password" => "your-password", "totp_code" => "123456", // omit if 2FA is not enabled "new_api_key" => true, // optional ]), CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Content-Type: application/json"], ]); $data = json_decode(curl_exec($ch), true); curl_close($ch); $token = $data["token"]; // use as: Authorization: Bearer <token> if (isset($data["api_key"])) echo "New API key — store it now: " . $data["api_key"];
// Cargo.toml: // serde_json = "1" // reqwest = { version = "0.12", features = ["blocking", "json"] } const BASE_URL: &str = "https://www.anirena.com"; fn main() { let client = reqwest::blocking::Client::new(); // One request: authenticate (with 2FA if enabled) and get a bearer token. // Set new_api_key:true to also receive a brand-new permanent API key. let data: serde_json::Value = client .post(format!("{BASE_URL}/api/v1/auth/login")) .json(&serde_json::json!({ "login": "your-username", // username or email "password": "your-password", "totp_code": "123456", // omit if 2FA is not enabled "new_api_key": true, // optional })) .send().unwrap() .json().unwrap(); let token = data["token"].as_str().unwrap(); // Authorization: Bearer <token> if let Some(key) = data["api_key"].as_str() { println!("New API key — store it now: {key}"); } }
Stap 2 — Upload een torrent
/api/v1/torrentsStuur een eenvoudig JSON POST-verzoek met het bearer-token in de Authorization-header.
Verzoekbody
| Veld | Type | Vereist | Beschrijving |
|---|---|---|---|
torrent | string | Ja | Base64-gecodeerde inhoud van het .torrent-bestand. |
category | string | Ja | Categorieslug: anime, manga, audio, literature, live, pictures, software, hentai, other. |
name | string | Nee | Overschrijf de weergavenaam van de torrent. |
sub_category | string | Nee | Subcategorieslug (bijv. raw, sub-audio). Moet bij de gekozen categorie horen. |
languages | string[] | Nee | Array van BCP 47-taalcodes (bijv. en, ja). |
group_id | string | Nee | UUID van een groep waarvan je lid bent om deze release aan te koppelen. |
description | string | Nee | Markdown-beschrijving van de release (max. 65535 tekens). |
comment | string | Nee | Overschrijf het ingesloten torrentcommentaarveld. |
is_private | boolean | Nee | Stel in op true om de privevlag in de torrent in te schakelen. |
comments_enabled | boolean | Nee | Reacties op deze torrent toestaan. Standaard true (ingeschakeld). |
anime_id | string | Nee | UUID van een anime-vermelding om aan deze torrent te koppelen. Haal de UUID op via GET /api/v1/anime/search. Geeft 400 terug als de UUID niet overeenkomt met een bekende vermelding. |
announce | string | Nee | Overschrijf of voeg de primaire announce-URL toe. |
trackers | string | Nee | Lijst van extra tracker-URLs, een per regel. Een lege regel tussen URLs maakt een nieuwe tier aan. |
test | boolean | Nee | Stel in op true voor een droogloop: het verzoek wordt volledig gevalideerd maar de torrent wordt niet opgeslagen. Gebruik dit om te controleren of uw payload correct is vóór de daadwerkelijke indiening. |
Droogloop-successantwoord — 200 OK
{
"ok": true,
"test": true,
"name": "My Torrent Title",
"info_hash_v1": "aabbccddeeff...",
"info_hash_v2": null
}Beschikbare taalcodes
abaaafaksqamarar-001anhyasavaeayazbmbaeubebnbhbibsbrbgmyyuecachcenyzhzh-HKzh-Hanszh-SGzh-TWcucvkwcocrhrcsdadvnlnl-BEdzenen-USeoeteefofjfilfifrfr-CAffgllgkadede-ATelgnguhthahehzhihohuisioigidiaieiuikgaitjajvklknkrkskkkmkirwrnkvkgkokjkukylolalvlilnltlulbmkmgmsmlmtgvmimrmhmnnanvngnendsenonbnnocorojomospipsfaplptpt-BRpaqurormrusmsgsascgdsrsr-Latnsniisdsiskslsonrsteses-419es-MXsuswsssvtltytgtatttethbotitotstntrtktwukuruguzvevivowacyfywoxhyiyozazuVoorbeeldverzoek
# pip install requests import base64, pathlib, requests API_KEY = "YOUR_API_KEY" BASE_URL = "https://www.anirena.com" # Step 1: exchange API key for a short-lived bearer token auth = requests.post( f"{BASE_URL}/api/v1/auth/token", headers={"Authorization": f"ApiKey {API_KEY}"}, ) auth.raise_for_status() token = auth.json()["token"] # Step 2: upload — plain JSON with the bearer token torrent_b64 = base64.b64encode(pathlib.Path("file.torrent").read_bytes()).decode() resp = requests.post( f"{BASE_URL}/api/v1/torrents", json={ "torrent": torrent_b64, "category": "anime", "sub_category": "raw", "languages": ["ja"], "description": "# My Release\n\nRelease notes here.", "is_private": False, }, headers={"Authorization": f"Bearer {token}"}, ) resp.raise_for_status() data = resp.json() token = resp.headers.get("X-New-Token", token) # save for next request print(data["id"], data["name"]) # torrent UUID and title
// Built-in modules only — requires Node.js 18+ (for global fetch) const fs = require("fs"); const API_KEY = "YOUR_API_KEY"; const BASE_URL = "https://www.anirena.com"; // Step 1: exchange API key for a short-lived bearer token let authResp = await fetch(`${BASE_URL}/api/v1/auth/token`, { method: "POST", headers: { Authorization: `ApiKey ${API_KEY}` }, }); let { token } = await authResp.json(); // Step 2: upload — plain JSON with the bearer token const torrentB64 = fs.readFileSync("file.torrent").toString("base64"); const resp = await fetch(`${BASE_URL}/api/v1/torrents`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` }, body: JSON.stringify({ torrent: torrentB64, category: "anime", sub_category: "raw", languages: ["ja"], description: "# My Release\n\nRelease notes here.", is_private: false, }), }); const data = await resp.json(); token = resp.headers.get("x-new-token") ?? token; // save for next request console.log(data.id, data.name); // torrent UUID and title
// Requires: curl extension (enabled by default in PHP 8+) <?php define("API_KEY", "YOUR_API_KEY"); define("BASE_URL", "https://www.anirena.com"); // Step 1: exchange API key for a short-lived bearer token $ch = curl_init(BASE_URL . "/api/v1/auth/token"); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Authorization: ApiKey " . API_KEY], ]); $token = json_decode(curl_exec($ch), true)["token"]; curl_close($ch); // Step 2: upload — plain JSON with the bearer token $torrentB64 = base64_encode(file_get_contents("file.torrent")); $respHeaders = []; $ch = curl_init(BASE_URL . "/api/v1/torrents"); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode([ "torrent" => $torrentB64, "category" => "anime", "sub_category" => "raw", "languages" => ["ja"], "description" => "# My Release\n\nRelease notes here.", "is_private" => false, ]), CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADERFUNCTION => function($ch, $h) use (&$respHeaders) { $respHeaders[] = $h; return strlen($h); }, CURLOPT_HTTPHEADER => [ "Content-Type: application/json", "Authorization: Bearer " . $token, ], ]); $data = json_decode(curl_exec($ch), true); curl_close($ch); foreach ($respHeaders as $h) { // save new token for next request if (stripos($h, "X-New-Token:") === 0) $token = trim(substr($h, strlen("X-New-Token:"))); } echo $data["id"] . " " . $data["name"]; // torrent UUID and title
// Cargo.toml: // base64 = "0.22" // serde_json = "1" // reqwest = { version = "0.12", features = ["blocking", "json"] } use base64::{engine::general_purpose::STANDARD as B64, Engine}; const API_KEY: &str = "YOUR_API_KEY"; const BASE_URL: &str = "https://www.anirena.com"; fn main() { let client = reqwest::blocking::Client::new(); // Step 1: exchange API key for a short-lived bearer token let auth: serde_json::Value = client .post(format!("{BASE_URL}/api/v1/auth/token")) .header("Authorization", format!("ApiKey {API_KEY}")) .send().unwrap().json().unwrap(); let mut token = auth["token"].as_str().unwrap().to_string(); // Step 2: upload — plain JSON with the bearer token let torrent_b64 = B64.encode(std::fs::read("file.torrent").unwrap()); let resp = client .post(format!("{BASE_URL}/api/v1/torrents")) .header("Authorization", format!("Bearer {token}")) .json(&serde_json::json!({ "torrent": torrent_b64, "category": "anime", "sub_category": "raw", "languages": ["ja"], "description": "# My Release\n\nRelease notes here.", "is_private": false })) .send().unwrap(); if let Some(t) = resp.headers().get("x-new-token") { token = t.to_str().unwrap().to_string(); // save for next request } let data: serde_json::Value = resp.json().unwrap(); println!("{} {}", data["id"], data["name"]); // torrent UUID and title }
Succesvol antwoord — 200 OK
{
"ok": true,
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "My Torrent Title",
"info_hash_v1": "aabbccddeeff...",
"info_hash_v2": null
}Foutantwoorden
| HTTP-status | Betekenis |
|---|---|
400 | Ongeldig verzoekbody of ontbrekend verplicht veld. |
401 | Ontbrekend, verlopen of al geroteerd bearer-token. Verifieer opnieuw via POST /api/v1/auth/token. |
403 | Account verbannen, uitgeschakeld of IP geblokkeerd. |
409 | Dubbele torrent — dezelfde info-hash bestaat al. |
422 | Torrentbestand kon niet worden geparsed of validatie mislukt (verboden patroon, ongeldige structuur). |
429 | Snelheidslimiet overschreden. Probeer opnieuw na het resetten van het venster. |
503 | Site is in onderhoud of alleen-lezenmodus. |
Snelheidslimiet
API-uploads zijn onderworpen aan een configureerbare snelheidslimiet los van de webinterface. De limiet en het venster worden ingesteld door de sitebeheerder. Wanneer de snelheidslimiet wordt overschreden, geeft de API 429 Too Many Requests terug. De limiet is per API-sleutel.
Torrentbestanden genereren met torrent-builder
torrent-builder is een open-source CLI-tool gebouwd op libtorrent-rasterbar waarmee je BitTorrent v1, v2 en hybrid .torrent-bestanden kunt maken vanaf de opdrachtregel. Het werkt perfect samen met de AniRena upload API — genereer het bestand lokaal en POST het vervolgens direct naar de tracker. cantalupo555/torrent-builder.
Bouwen vanuit broncode
Vereist CMake >= 3.28.3 en libtorrent-rasterbar >= 2.0.11. Kloon de repository en bouw met CMake:
# Install system dependencies sudo apt-get install build-essential cmake libtorrent-rasterbar-dev # Clone & build git clone https://github.com/cantalupo555/torrent-builder.git cd torrent-builder mkdir build && cd build cmake .. && cmake --build .
# Install dependencies via Homebrew brew install cmake libtorrent-rasterbar # Clone & build git clone https://github.com/cantalupo555/torrent-builder.git cd torrent-builder mkdir build && cd build cmake .. && cmake --build .
Belangrijkste vlaggen
| Veld | Beschrijving |
|---|---|
--path | Pad naar het te verpakken bestand of map (vereist). |
--output | Naam van het uitvoer-.torrent-bestand (vereist). |
--version | BitTorrent-indeling — 1 = v1, 2 = v2, 3 = hybrid (standaard: 3). |
--tracker | Voeg een tracker-announce-URL toe. Herhaal de vlag om meerdere trackers toe te voegen. |
--comment | Sluit een metagegevenscommentaarreeks in de torrent in. |
--private | Stel de privévlag in om verspreiding te beperken tot alleen de vermelde trackers. |
--piece-size | Stukgrootte in KB (16-32768). Laat ongesteld voor automatische selectie. |
-i | Start de stapsgewijze interactieve configuratiemodus. |
End-to-end workflow: bouwen -> uploaden
De onderstaande voorbeelden bouwen een hybrid torrent met torrent-builder, verifiëren dan bij de AniRena API en uploaden het resultaat in één script.
# pip install requests import base64, subprocess, requests API_KEY = "YOUR_API_KEY" BASE_URL = "https://www.anirena.com" # Step 1: build the torrent with torrent-builder # --version 1=v1 2=v2 3=hybrid (default) subprocess.run([ "./torrent-builder/build/torrent_builder", "--path", "/data/my_release", "--output", "my_release.torrent", "--version", "3", # hybrid "--tracker", "udp://open.tracker.gg:6969/announce", "--comment", "My Release", "--creator", "--creation-date", ], check=True) # Step 2: authenticate token = requests.post( f"{BASE_URL}/api/v1/auth/token", headers={"Authorization": f"ApiKey {API_KEY}"}, ).json()["token"] # Step 3: upload torrent_b64 = base64.b64encode(open("my_release.torrent", "rb").read()).decode() resp = requests.post( f"{BASE_URL}/api/v1/torrents", json={ "torrent": torrent_b64, "category": "anime", "sub_category": "raw", "languages": ["ja"], "comments_enabled": True, }, headers={"Authorization": f"Bearer {token}"}, ) resp.raise_for_status() data = resp.json() print(data["id"], data["name"])
// Built-in modules — Node.js 18+ const fs = require("fs"); const { execFileSync } = require("child_process"); const API_KEY = "YOUR_API_KEY"; const BASE_URL = "https://www.anirena.com"; // Step 1: build the torrent (--version 1=v1, 2=v2, 3=hybrid) execFileSync("./torrent-builder/build/torrent_builder", [ "--path", "/data/my_release", "--output", "my_release.torrent", "--version", "3", "--tracker", "udp://open.tracker.gg:6969/announce", "--comment", "My Release", "--creator", "--creation-date", ]); // Step 2: authenticate let { token } = await (await fetch(`${BASE_URL}/api/v1/auth/token`, { method: "POST", headers: { Authorization: `ApiKey ${API_KEY}` }, })).json(); // Step 3: upload const torrentB64 = fs.readFileSync("my_release.torrent").toString("base64"); const resp = await fetch(`${BASE_URL}/api/v1/torrents`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` }, body: JSON.stringify({ torrent: torrentB64, category: "anime", sub_category: "raw", languages: ["ja"], comments_enabled: true, }), }); const data = await resp.json(); console.log(data.id, data.name);
// PHP 8+ with curl and proc_open <?php define("API_KEY", "YOUR_API_KEY"); define("BASE_URL", "https://www.anirena.com"); // Step 1: build the torrent (version: 1=v1, 2=v2, 3=hybrid) exec(implode(" ", array_map("escapeshellarg", [ "./torrent-builder/build/torrent_builder", "--path", "/data/my_release", "--output", "my_release.torrent", "--version", "3", "--tracker", "udp://open.tracker.gg:6969/announce", "--comment", "My Release", "--creator", "--creation-date", ]))); // Step 2: authenticate $ch = curl_init(BASE_URL . "/api/v1/auth/token"); curl_setopt_array($ch, [CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Authorization: ApiKey " . API_KEY]]); $token = json_decode(curl_exec($ch), true)["token"]; curl_close($ch); // Step 3: upload $torrentB64 = base64_encode(file_get_contents("my_release.torrent")); $respHeaders = []; $ch = curl_init(BASE_URL . "/api/v1/torrents"); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode([ "torrent" => $torrentB64, "category" => "anime", "sub_category" => "raw", "languages" => ["ja"], "comments_enabled" => true, ]), CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADERFUNCTION => function($ch, $h) use (&$respHeaders) { $respHeaders[] = $h; return strlen($h); }, CURLOPT_HTTPHEADER => ["Content-Type: application/json", "Authorization: Bearer " . $token], ]); $data = json_decode(curl_exec($ch), true); curl_close($ch); echo $data["id"] . " " . $data["name"];
// Cargo.toml: // base64 = "0.22" // serde_json = "1" // reqwest = { version = "0.12", features = ["blocking", "json"] } use base64::{engine::general_purpose::STANDARD as B64, Engine}; use std::process::Command; const API_KEY: &str = "YOUR_API_KEY"; const BASE_URL: &str = "https://www.anirena.com"; fn main() { // Step 1: build the torrent (--version 1=v1, 2=v2, 3=hybrid) Command::new("./torrent-builder/build/torrent_builder") .args([ "--path", "/data/my_release", "--output", "my_release.torrent", "--version", "3", "--tracker", "udp://open.tracker.gg:6969/announce", "--comment", "My Release", "--creator", "--creation-date", ]) .status().expect("torrent_builder failed"); let client = reqwest::blocking::Client::new(); // Step 2: authenticate let auth: serde_json::Value = client .post(format!("{BASE_URL}/api/v1/auth/token")) .header("Authorization", format!("ApiKey {API_KEY}")) .send().unwrap().json().unwrap(); let token = auth["token"].as_str().unwrap().to_string(); // Step 3: upload let torrent_b64 = B64.encode(std::fs::read("my_release.torrent").unwrap()); let resp: serde_json::Value = client .post(format!("{BASE_URL}/api/v1/torrents")) .header("Authorization", format!("Bearer {token}")) .json(&serde_json::json!({ "torrent": torrent_b64, "category": "anime", "sub_category": "raw", "languages": ["ja"], "comments_enabled": true, })) .send().unwrap().json().unwrap(); println!("{} {}", resp["id"], resp["name"]); }
Torrent-metadata zoeken
/api/v1/torrents/searchStuur een eenvoudig JSON POST-verzoek om torrentoverzichten op te halen met dezelfde zoek- en filteropties die beschikbaar zijn op de website. Het .torrent-bestand zelf wordt niet teruggegeven — gebruik de normale downloadroute daarvoor.
# pip install requests (token already obtained — see upload example) resp = requests.post( f"{BASE_URL}/api/v1/torrents/search", json={"q": "Sword Art Online", "category": "anime", "per_page": 25}, headers={"Authorization": f"Bearer {token}"}, ) resp.raise_for_status() data = resp.json() token = resp.headers.get("X-New-Token", token) # save for next request for t in data["torrents"]: print(t["title"], "-", t["magnet"])
// token already obtained — see upload example const resp = await fetch(`${BASE_URL}/api/v1/torrents/search`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` }, body: JSON.stringify({ q: "Sword Art Online", category: "anime", per_page: 25 }), }); const data = await resp.json(); token = resp.headers.get("x-new-token") ?? token; // save for next request data.torrents.forEach(t => console.log(t.title, "-", t.magnet));
// token already obtained — see upload example $respHeaders = []; $ch = curl_init(BASE_URL . "/api/v1/torrents/search"); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode([ "q" => "Sword Art Online", "category" => "anime", "per_page" => 25 ]), CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADERFUNCTION => function($ch, $h) use (&$respHeaders) { $respHeaders[] = $h; return strlen($h); }, CURLOPT_HTTPHEADER => [ "Content-Type: application/json", "Authorization: Bearer " . $token, ], ]); $data = json_decode(curl_exec($ch), true); curl_close($ch); foreach ($respHeaders as $h) { // save new token for next request if (stripos($h, "X-New-Token:") === 0) $token = trim(substr($h, strlen("X-New-Token:"))); } foreach ($data["torrents"] as $t) { echo $t["title"] . " - " . $t["magnet"] . "\n"; }
// client and token already obtained — see upload example let resp = client .post(format!("{BASE_URL}/api/v1/torrents/search")) .header("Authorization", format!("Bearer {token}")) .json(&serde_json::json!({"q": "Sword Art Online", "category": "anime", "per_page": 25})) .send().unwrap(); if let Some(t) = resp.headers().get("x-new-token") { token = t.to_str().unwrap().to_string(); // save for next request } let data: serde_json::Value = resp.json().unwrap(); for t in data["torrents"].as_array().unwrap() { println!("{} - {}", t["title"], t["magnet"]); }
Zoekparameters
| Veld | Type | Vereist | Beschrijving |
|---|---|---|---|
q | string | Nee | Vrije tekst zoeken. Ondersteunt group:slug, group:"Name", user:name voorvoegsels. |
category | string | Nee | Categorie-slug (bijv. "anime"). |
sub_category | string | Nee | Subcategorie-slug (bijv. "raw"). |
languages | string[] | Nee | Array van BCP 47-taalcodes (bijv. en, ja). |
sort | string | Nee | Sorteerveld: date (standaard), size, seeders, leechers, completed, title. |
order | string | Nee | Sorteerrichting: desc (standaard) of asc. |
page | integer | Nee | Paginanummer, vanaf 1 (standaard 1). |
per_page | integer | Nee | Resultaten per pagina, 1–250 (standaard 50). |
hide_adult | boolean | Nee | Volwassen-categorietorrents uitsluiten. Standaard true voor gewone gebruikers. |
show_dead | boolean | Nee | Wanneer false (standaard) worden torrents die ouder zijn dan de dead-torrent-grace-periode en geen actieve seeders hebben, uitgesloten. Zet op true om ze op te nemen. |
Antwoord
{
"total": 1234,
"page": 1,
"per_page": 50,
"total_pages": 25,
"from": 1,
"to": 50,
"torrents": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "My Release Title",
"info_hash_v1": "aabbccddeeff...",
"info_hash_v2": null,
"size_fmt": "1.4 GB",
"completed": 42,
"seeders": 10,
"leechers": 3,
"languages": ["ja", "en"],
"comment_count": 7,
"created_at": "2024-01-15 12:34",
"cat_slug": "anime",
"sub_slug": "raw",
"group_name": null,
"uploader": "username",
"magnet": "magnet:?xt=urn:btih:..."
}
]
}comment_count — Aantal niet-verwijderde reacties op deze torrent.
Zoeklimiet
Zoekaanvragen zijn onderworpen aan een afzonderlijk instelbare limiet (standaard 60 verzoeken per 60 seconden per API-sleutel). Bij overschrijding wordt 429 Too Many Requests teruggegeven. Stafaccounts zijn vrijgesteld.
Torrent-details ophalen
/api/v1/torrent/{id}Haal de volledige metadata van één torrent op — inclusief velden die het zoekendpoint weglaat, zoals de Markdown-beschrijving, het ingebedde .torrent-commentaar, de bestandslijst met grootte per bestand en de volledige tracker-tier-indeling. Live aantallen seeders en leechers worden uit de tracker gelezen wanneer beschikbaar.
Antwoord
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "My Release Title",
"info_hash_v1": "aabbccddeeff...",
"info_hash_v2": null,
"size_fmt": "1.4 GB",
"completed": 42,
"seeders": 10,
"leechers": 3,
"ext_seeders": 128,
"ext_leechers": 14,
"created_at": "2024-01-15 12:34",
"torrent_created": "2024-01-15 12:30",
"created_by_client": "mktorrent 1.1",
"cat_name": "Anime",
"cat_slug": "anime",
"sub_name": "Raw",
"sub_slug": "raw",
"group_name": null,
"group_slug": null,
"uploader": "username",
"uploader_id": "...",
"description": "# My Release\n\nRelease notes here.",
"comment": "",
"is_private": false,
"magnet": "magnet:?xt=urn:btih:...",
"languages": [
{ "code": "ja", "name": "Japanese", "country_code": "jp" }
],
"tracker_tiers": [
{ "tier": 0, "urls": ["udp://tracker.example.org:6969/announce"] }
],
"files": [
{ "path": "My Release/episode-01.mkv", "size": 1503238553 }
],
"comments_enabled": true,
"comments_locked": false,
"comment_count": 7
}seeders, leechers — Live aantallen uit de interne tracker; beide rapporteren 0 wanneer de tracker-store geen vermelding voor deze info hash heeft of onbereikbaar is.
ext_seeders, ext_leechers — Hoogste aantal seeders en leechers gerapporteerd door één enkele externe tracker die voor deze torrent is gescrapet. Trackers die dezelfde swarm volgen overlappen, dus wordt het maximum gebruikt in plaats van de som; beide rapporteren 0 wanneer geen enkele tracker scrape-gegevens heeft voor deze info hash.
Foutantwoorden
| HTTP-status | Betekenis |
|---|---|
400 | De torrent-id moet een UUID van 36 tekens met streepjes zijn of een 32-tekens kale hex-string. |
401 | Ontbrekend, verlopen of al geroteerd bearer-token. Verifieer opnieuw via POST /api/v1/auth/token. |
404 | Torrent niet gevonden. |
429 | Snelheidslimiet overschreden. Probeer opnieuw na het resetten van het venster. |
503 | Site is in onderhoud of alleen-lezenmodus. |
Torrentreacties ophalen
/api/v1/torrents/{id}/commentsHaal gepagineerde reacties op voor een torrent. Het aantal reacties per pagina wordt beheerd door de COMMENT_PER_PAGE-instelling in het .env-bestand van de server (standaard 20). Alleen torrents met ingeschakelde reacties retourneren resultaten — alle anderen retourneren 403.
Queryparameters
| Veld | Type | Vereist | Beschrijving |
|---|---|---|---|
page | integer | Nee | Paginanummer, startend bij 1 (standaard 1). |
# pip install requests (token already obtained — see upload example) TORRENT_ID = "550e8400-e29b-41d4-a716-446655440000" resp = requests.get( f"{BASE_URL}/api/v1/torrents/{TORRENT_ID}/comments", params={"page": 1}, headers={"Authorization": f"Bearer {token}"}, ) resp.raise_for_status() data = resp.json() token = resp.headers.get("X-New-Token", token) # save for next request for c in data["comments"]: print(c["username"], "-", c["body"])
// token already obtained — see upload example const TORRENT_ID = "550e8400-e29b-41d4-a716-446655440000"; const resp = await fetch(`${BASE_URL}/api/v1/torrents/${TORRENT_ID}/comments?page=1`, { headers: { Authorization: `Bearer ${token}` }, }); const data = await resp.json(); token = resp.headers.get("x-new-token") ?? token; // save for next request data.comments.forEach(c => console.log(c.username, "-", c.body));
// token already obtained — see upload example $torrentId = "550e8400-e29b-41d4-a716-446655440000"; $respHeaders = []; $ch = curl_init(BASE_URL . "/api/v1/torrents/{$torrentId}/comments?page=1"); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADERFUNCTION => function($ch, $h) use (&$respHeaders) { $respHeaders[] = $h; return strlen($h); }, CURLOPT_HTTPHEADER => ["Authorization: Bearer " . $token], ]); $data = json_decode(curl_exec($ch), true); curl_close($ch); foreach ($respHeaders as $h) { // save new token for next request if (stripos($h, "X-New-Token:") === 0) $token = trim(substr($h, strlen("X-New-Token:"))); } foreach ($data["comments"] as $c) { echo $c["username"] . " - " . $c["body"] . "\n"; }
// client and token already obtained — see upload example let torrent_id = "550e8400-e29b-41d4-a716-446655440000"; let resp = client .get(format!("{BASE_URL}/api/v1/torrents/{torrent_id}/comments?page=1")) .header("Authorization", format!("Bearer {token}")) .send().unwrap(); if let Some(t) = resp.headers().get("x-new-token") { token = t.to_str().unwrap().to_string(); // save for next request } let data: serde_json::Value = resp.json().unwrap(); for c in data["comments"].as_array().unwrap() { println!("{} - {}", c["username"], c["body"]); }
Antwoord
{
"torrent_id": "550e8400-e29b-41d4-a716-446655440000",
"page": 1,
"per_page": 20,
"total": 45,
"total_pages": 3,
"comments": [
{
"id": "...",
"user_id": "...",
"username": "uploader",
"role": "user",
"author_banned": false,
"body": "Great release!",
"created_at": "2024-01-15 12:34:00",
"edited_at": null,
"edited_by_username": null,
"deleted_at": null
}
]
}Het veld body is een lege reeks wanneer de reactieauteur verbannen is of de reactie is verwijderd. De vlag author_banned geeft aan welk geval van toepassing is.
Foutantwoorden
| HTTP-status | Betekenis |
|---|---|
401 | Ontbrekend, verlopen of al geroteerd bearer-token. Verifieer opnieuw via POST /api/v1/auth/token. |
403 | Reacties zijn uitgeschakeld voor deze torrent. |
404 | Torrent niet gevonden. |
503 | Site is in onderhoud of alleen-lezenmodus. |
Anime-items zoeken
/api/v1/anime/search?q=<query>Zoek anime-vermeldingen op titel om hun UUID te verkrijgen. De UUID kan worden meegegeven als anime_id in de uploadtekst om een torrent te koppelen aan een anime-vermelding tijdens het uploaden, of worden gebruikt met PUT /api/torrents/{id}/anime na het uploaden. Geen authenticatie vereist. Onderhevig aan dezelfde snelheidslimiet als torrent zoeken (standaard 60 verzoeken per 60 seconden per IP).
# pip install requests (no authentication required)
resp = requests.get(
f"{BASE_URL}/api/v1/anime/search",
params={"q": "Sword Art Online", "page": 1, "per_page": 10},
)
resp.raise_for_status()
for item in resp.json()["results"]:
print(item["id"], "-", item["title"])// No authentication required
const resp = await fetch(
`${BASE_URL}/api/v1/anime/search?q=${encodeURIComponent("Sword Art Online")}&page=1&per_page=10`
);
const data = await resp.json();
data.results.forEach(item => console.log(item.id, "-", item.title));// No authentication required
$ch = curl_init(BASE_URL . "/api/v1/anime/search?" . http_build_query([
"q" => "Sword Art Online", "page" => 1, "per_page" => 10,
]));
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
foreach ($data["results"] as $item) {
echo $item["id"] . " - " . $item["title"] . "\n";
}// No authentication required
let data: serde_json::Value = reqwest::blocking::get(
format!("{BASE_URL}/api/v1/anime/search?q=Sword+Art+Online&page=1&per_page=10")
).unwrap().json().unwrap();
for item in data["results"].as_array().unwrap() {
println!("{} - {}", item["id"], item["title"]);
}Queryparameters
| Veld | Type | Vereist | Beschrijving |
|---|---|---|---|
q | string | Ja | Zoekstring voor titel (vereist). Vergeleken met titel en synoniemen. |
page | integer | Nee | Paginanummer, vanaf 1 (standaard 1). |
per_page | integer | Nee | Resultaten per pagina, 1–50 (standaard 10). |
Reactie
{
"total": 42,
"page": 1,
"per_page": 10,
"total_pages": 5,
"results": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"title": "Sword Art Online",
"anime_type": "TV",
"episodes": 25,
"status": "FINISHED",
"season": "FALL",
"season_year": 2012,
"picture": "https://cdn.myanimelist.net/images/anime/...",
"thumbnail": "https://cdn.myanimelist.net/images/anime/...",
"duration_secs": 1440
}
]
}Groepen weergeven en ophalen
/api/v1/groupsGeeft een gepagineerde lijst van openbare groepen (ingeschakeld en niet vergrendeld). Vereist Bearer-tokenauthenticatie.
/api/v1/groups/{id_or_slug}Geeft een enkele openbare groep op basis van numeriek ID of slug. Geeft 404 terug als de groep uitgeschakeld of vergrendeld is.
Queryparameters (alleen lijst)
| Veld | Type | Vereist | Beschrijving |
|---|---|---|---|
q | string | Nee | Filter op groepsnaam (optioneel, subtekenreeksovereenkomst). |
page | integer | Nee | Paginanummer (standaard 1). |
per_page | integer | Nee | Resultaten per pagina, 1–100 (standaard 20). |
sort | string | Nee | Sorteerkolom: name | slug | members | torrents | created (standaard name). |
order | string | Nee | Sorteerrichting: asc of desc (standaard asc). |
Antwoord (lijst)
{
"total": 12,
"page": 1,
"per_page": 20,
"total_pages": 1,
"groups": [
{
"id": 1,
"name": "SubsPlease",
"slug": "subsplease",
"subdomain_slug": "subsplease",
"description": "Weekly simulcast batches.",
"owner": "admin",
"member_count": 42,
"torrent_count": 1337,
"created_at": "2024-01-15 12:34"
}
]
}Antwoord (enkel)
{
"id": 1,
"name": "SubsPlease",
"slug": "subsplease",
"subdomain_slug": "subsplease",
"description": "Weekly simulcast batches.",
"owner": "admin",
"member_count": 42,
"torrent_count": 1337,
"created_at": "2024-01-15 12:34"
}Foutantwoorden
| HTTP-status | Betekenis |
|---|---|
401 | Ontbrekend, verlopen of al geroteerd bearer-token. Verifieer opnieuw via POST /api/v1/auth/token. |
404 | Groep niet gevonden of niet openbaar toegankelijk. |
429 | Snelheidslimiet overschreden. Probeer opnieuw na het resetten van het venster. |
503 | Site is in onderhoud of alleen-lezenmodus. |
8. Donaties
Als u AniRena wilt ondersteunen en wilt helpen bij het dekken van de kosten voor het hosten van onze servers en diensten, kunt u een donatie sturen naar een van de volgende cryptocurrency-wallets:
bc1qy2h3ddq6ak5damvnf4r5vu3ydehhxrcq8gllwn0xCbaFe03832F95F86AF2536d52710e78C63b62Cd33ucetj2XDGHQg9PVRPMxerNi7c6kX7GJkjQNg9yjwGegLbpt61yX3RjGtB1Ef8vgVz6Hr6baQsTjVkElke donatie, groot of klein, wordt zeer gewaardeerd en gaat direct naar het draaiende houden van AniRena. Bedankt voor uw steun!
9. Software
AniRena Player is een gratis desktop-app waarmee je video rechtstreeks kunt streamen vanuit op deze site geïndexeerde torrents — je hoeft niet te wachten tot de volledige download klaar is. Plak gewoon een magnet-link of open een .torrent-bestand, en het afspelen begint zodra er voldoende data beschikbaar is.
Beide builds zijn volledig standalone — alle afhankelijkheden zitten in het uitvoerbare bestand. Geen installer, geen runtime nodig — gewoon downloaden en uitvoeren.
Installer (.exe). Werkt zichzelf bij in de app.
Schijfkopie (.dmg) voor Apple Silicon-Macs (M1 en nieuwer). Werkt zichzelf bij in de app.
Schijfkopie (.dmg) voor Intel-Macs. Werkt zichzelf bij in de app.
Draagbaar enkel bestand, geen installatie nodig. Het enige Linux-formaat met automatische update binnen de app.
Installatie: sudo apt install ./<file>.deb — updates via apt of een nieuwe download, niet in de app.
Installatie: sudo dnf install ./<file>.rpm — updates via dnf of een nieuwe download, niet in de app.
Sideload op 64-bit ARM Android-apparaten (de meeste moderne telefoons / tablets). Bijwerken door een nieuwe APK te downloaden.
Oudere versies
Sideload op 32-bit ARM Android-apparaten (oudere telefoons / tablets). Bijwerken door een nieuwe APK te downloaden.