Skip to content

Instantly share code, notes, and snippets.

@iAmNikola
Last active March 9, 2026 21:51
Show Gist options
  • Select an option

  • Save iAmNikola/f7b5f6bd18b0cc3832874a1d1c72a55e to your computer and use it in GitHub Desktop.

Select an option

Save iAmNikola/f7b5f6bd18b0cc3832874a1d1c72a55e to your computer and use it in GitHub Desktop.
Download archive footage from a folder within Fishtank.live archive. NOTE: You DON'T need a season pass to have access to archives this way!
from concurrent.futures import ThreadPoolExecutor
import json
from pathlib import Path
import sys
from typing import List
import requests
### How to extract the AUTHTOKEN:
### 1. Open DevTools (f12 on chrome)
### 2. Open Network tab
### 3. Go to fishtank.live
### 4. Find request with name "token?key=....." and click it
### 5. Open Response tab
### 6. Copy and paste bellow the "acces_token" value
AUTHTOKEN = '<AUTHTOKEN>'
class Globals:
archive_headers = {'Authtoken': AUTHTOKEN}
download_headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36', 'Accept-Language': 'en-RS,en-US;q=0.9,en;q=0.8', 'Authtoken': AUTHTOKEN, 'Origin': 'https://www.fishtank.live', 'Referer': 'https://www.fishtank.live/archive', 'Sec-Ch-Ua': '"Google Chrome";v="113", "Chromium";v="113", "Not-A.Brand";v="24"', 'Sec-Ch-Ua-Mobile': '?0', 'Sec-Ch-Ua-Platform': 'Windows', 'Sec-Fetch-Dest': 'empty', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Site': 'same-origin', 'Cookie': '', 'Accept-Encoding': 'gzip, deflate'}
archive_url = 'https://www.fishtank.live/api/archive/'
download_url = 'https://www.fishtank.live/api/archive/download'
def get_videos(camera: str):
response = requests.get(f'{Globals.archive_url}{camera}', headers= Globals.archive_headers)
if response.status_code == 403:
raise requests.exceptions.InvalidHeader('Bad authtoken.')
videos: List[str] = [x['ObjectName'] for x in json.loads(response.text)['files'] if x['ObjectName'].endswith('.mp4')]
camera_folder = Path(__file__).resolve().parent / camera
camera_folder.mkdir(exist_ok=True)
with ThreadPoolExecutor(max_workers=6) as executor:
for video in videos:
try:
executor.submit(download_video, video, camera)
except KeyError:
print('The authtoken has expired. Refresh fishtank.live and get a new one.')
sys.exit()
def download_video(video: str, camera: str):
video_path = Path(__file__).resolve().parent / camera / video
if video_path.exists():
return
response = requests.post(Globals.download_url, data={'path': f'/{camera}/{video}'}, headers=Globals.download_headers)
with requests.get(json.loads(response.text)['url'], stream=True, headers=Globals.download_headers) as r:
r.raise_for_status()
with open(video_path, 'wb') as f:
for chunk in r.iter_content(chunk_size=2048):
f.write(chunk)
class Camera:
B1 = 'bedroom-1'
B2 = 'bedroom-2'
B3 = 'bedroom-3'
B4 = 'bedroom-4'
CONFESSIONAL = 'confessional'
BATHROOM = 'bathroom'
GARAGE = 'garage'
HALL_DOWN = 'hallway-downstairs'
HALL_UP = 'hallway-upstairs'
KITCHEN = 'kitchen'
LAUNDRY = 'laundry-room'
LIVING_ROOM = 'living-room'
if __name__ == '__main__':
import argparse
parsers = argparse.ArgumentParser()
parsers.add_argument('camera', nargs='?', default=Camera.LIVING_ROOM)
args = parsers.parse_args([Camera.B1])
get_videos(args.camera)
@spitefulraven
Copy link

Is this still working after the post-finale Fishtank site updates? I get "bad authtoken" but I prob just did something wrong.

@iAmNikola
Copy link
Author

@r3wcifer if you used your authtoken (its really long) and cookies it should work. Checked again just now. Still works.

@spitefulraven
Copy link

@iAmNikola ah my bad, I overlooked the comments in the script about that, yeah sure enough it worked, geez that's pretty awesome lol

@iAmNikola
Copy link
Author

@r3wcifer Glad to hear that!

Note: If you are downloading some of the rooms with a lot of videos, you might need to reset your authtoken a couple times

@ecophobic
Copy link

so sick

@Trainerbob23
Copy link

alright how do i run this, please help

@ehl0el
Copy link

ehl0el commented Jun 13, 2023

^

@iAmNikola
Copy link
Author

@Trainerbob23 @ehl0el Updated script. Follow the instruction and you should have it running easy.

Thanks!

@KumiusMaximus
Copy link

Can't find 'Token?key=' request

@iAmNikola
Copy link
Author

@KumiusMaximus

Can't find 'Token?key=' request

Dig through all requests you make in your network tab and see if you can find your token in one of them. I think there are 2 different tokens so try either and see which one works.

Good luck!

@Boogadaboogadaboogada
Copy link

Could you do a video tutorial? Cannot wrap my head around this, I'm not good with computers.

@iAmNikola
Copy link
Author

@Infantrage
Copy link

Hey, I'm wondering if it's possible to do this on android?
I can't run the python file, I downloaded some python apps to no avail.

I can get chrome in developer mode, by tapping on the version number of the chrome release I run.
But the only thing it unlocks that may be relevant that I can see, is recording traces.
If I do that I get a .gz file that I can't open swell.

Sorry for being so stupid and annoying, but I had to try to get this to work, leaving no stone unturned.

Have a nice day!
Kind regards from Odin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment