Archival Tools - How to archive anything.

  • 🔎 If you see an alert for analytics.usips.org, this is a self-hosted system I am running as a test. It is GDPR compliant and collects no invasive information.
  • Want to keep track of this thread?
    Accounts can bookmark posts, watch threads for updates, and jump back to where you stopped reading.
    Create account
Crossposting from the Archive.today thread:
Does anyone else experience issues with Archive.today like I am?
 
Crossposting from the Archive.today thread:
Does anyone else experience issues with Archive.today like I am?
- Archive.today has always raped you with captchas. This problem isn't new.
- What are you trying to archive? This problem could be site specific
 
Crossposting from the Archive.today thread:
Does anyone else experience issues with Archive.today like I am?
Check your browser settings to see if DNS over HTTPS is enabled—if it is, try disabling it or switching your DNS provider to Cloudflare or Google. If the site is still down, try accessing it through its onion link (archiveiya74codqgiixo33q62qlrqtkgmcitqx5u2oeqnmn5bpcbiyd.onion), Also, as a quality-of-life tip, you can use a CAPTCHA-solving tool like Buster to make the process smoother.
 

Lolcow Archiver v1.1​

Lolcow Archiver (1.0)
For those who have been making use of this script, as a heads up, I've noticed that there is a memory leak caused by Playwright, which seemingly is ignored from the developers for years now. So if you have been running the script and making use of the YouTube community post archiving feature, you may of encountered this issue. I have updated the script to replace usage of Playwright with Selenium. I haven't noticed any issues with community post capture or memory leaks with this change yet, so I think it's ready for public consumption.

Python:
'''
Lolcow Archiver 1.1

This script can archive the following:

1) Kick/Twitch/YouTube Live Streams
2) YouTube Community Posts


This script requires yt-dlp to be installed for
video generation, in the same directory as this script.
You can get all the options for downloading yt-dlp
from it's Github page:

https://github.com/yt-dlp/yt-dlp/wiki/Installation


1.1: Replaced Playwright usage with Firefox and Selenium
    due to Playwright memory leaks unaddressed by their devs
  
    python -m pip install selenium

'''

import subprocess
import sys
import time
import os
from pathlib import Path
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.firefox.options import Options as FirefoxOptions
from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import TimeoutException, WebDriverException


# ---------------- SETTINGS ----------------

NEW_POST_COUNT = 0
NEW_STREAM_COUNT = 0


# ---------------- HELPERS ----------------

def read_last_seen(last_seen_file):
    if os.path.exists(last_seen_file):
        return Path(last_seen_file).read_text().strip()
    return None


def save_last_seen(last_seen_file, url):
    Path(last_seen_file).write_text(url)


def timestamp():
    return time.strftime("%Y-%m-%d_%H-%M-%S")


def usage():
    print("Usage: python lolcow_archiver.py Kick/Twitch/YouTube_URL Lolcow_Name [YouTube Community Post URL]")
    print("\nFor Example:")
    print("python lolcow_archiver.py https://www.youtube.com/@GlassWindow11/live Glass https://www.youtube.com/@GlassWindow11/posts")
    print("python lolcow_archiver.py https://kick.com/clavicular/ Clavicular")
    print("python lolcow_archiver.py https://kick.com/pwrworld/ PWR https://www.youtube.com/@PWRWorldOfficial/posts")
    print("\n\n")

def check_for_livestream(live_url):
    global NEW_STREAM_COUNT
    script_dir = Path(__file__).resolve().parent
    ytdlp_path = script_dir / "yt-dlp.exe"

    if not ytdlp_path.exists():
        print(time.strftime("%H:%M:%S", time.localtime()), f": Error: yt-dlp.exe not found at {ytdlp_path}")
        sys.exit(1)

    command = [
        str(ytdlp_path),
        "-o",
        "%(title).50B [%(id)s].%(ext)s", # Limit filename length if stream title too long
        "-t",
        "mp4",
        live_url,
    ]

    print(time.strftime("%H:%M:%S", time.localtime()), ": Launching yt-dlp...")
    try:
        result = subprocess.run(command, check=False)
        if result.returncode == 0:
            NEW_STREAM_COUNT += 1
    except Exception as e:
        print(time.strftime("%H:%M:%S", time.localtime()), f": Error while running yt-dlp: {e}")


def make_firefox_driver():
    options = FirefoxOptions()
    options.add_argument("-headless")

    # Do not wait for every YouTube resource to finish loading.
    # Selenium supports page load strategies:
    # normal = complete, eager = interactive, none = return immediately.
    options.page_load_strategy = "eager"

    # Keep YouTube UI text predictable so "Read more" selector works.
    options.set_preference("intl.accept_languages", "en-US,en")

    driver = webdriver.Firefox(options=options)
    driver.set_window_size(1920, 1080)

    # Keep this relatively short because we recover from timeouts below.
    driver.set_page_load_timeout(20)

    return driver

def safe_get(driver, url, label="page"):
    try:
        driver.get(url)
    except TimeoutException:
        print(
            time.strftime("%H:%M:%S", time.localtime()),
            f": Navigation timed out while loading {label}. Continuing with partially loaded page."
        )

        # Stop further loading so Selenium can continue interacting with the DOM.
        try:
            driver.execute_script("window.stop();")
        except WebDriverException:
            pass

def click_read_more_if_present(driver):
    # YouTube can render "Read more" in different custom elements depending on layout.
    candidates = driver.find_elements(
        By.CSS_SELECTOR,
        "tp-yt-paper-button, yt-formatted-string, button, span"
    )

    for element in candidates:
        try:
            text = (element.text or "").strip().lower()
            if text == "read more" or "read more" in text:
                driver.execute_script(
                    "arguments[0].scrollIntoView({block: 'center'});",
                    element
                )
                time.sleep(0.5)

                try:
                    element.click()
                except Exception:
                    driver.execute_script("arguments[0].click();", element)

                time.sleep(2)
                print(
                    time.strftime("%H:%M:%S", time.localtime()),
                    ": Large community post detected. Expanding the full text of the community post."
                )
                return True
        except Exception:
            continue

    return False


def check_for_new_post(lolcow_name, channel_posts_url):
    global NEW_POST_COUNT

    screenshot_prefix = f"{lolcow_name}_community_post_"
    last_seen_file = f"{lolcow_name}_last_seen.txt"

    driver = make_firefox_driver()

    try:
        print("\n")
        print(time.strftime("%H:%M:%S", time.localtime()), f": Checking community posts for {lolcow_name}...")

        # Navigate to Community Posts
        safe_get(driver, channel_posts_url, "YouTube community posts page")
        time.sleep(5)

        # Grab newest post link
        post_links = WebDriverWait(driver, 20).until(
            lambda d: d.find_elements(By.CSS_SELECTOR, "a[href*='/post/'], a[href*='post/']")
        )

        if not post_links:
            print(time.strftime("%H:%M:%S", time.localtime()), ": No posts located.")
            return

        latest_url = post_links[0].get_attribute("href")

        if not latest_url:
            print(time.strftime("%H:%M:%S", time.localtime()), ": No post URL found.")
            return

        if not latest_url.startswith("http"):
            latest_url = "https://www.youtube.com" + latest_url

        print(time.strftime("%H:%M:%S", time.localtime()), ": Latest post found:", latest_url)

        # Compare to last seen
        last_seen = read_last_seen(last_seen_file)

        if latest_url == last_seen:
            print(time.strftime("%H:%M:%S", time.localtime()), ": No new posts detected.")
            return

        print(time.strftime("%H:%M:%S", time.localtime()), ": NEW POST DETECTED!")
        NEW_POST_COUNT += 1

        save_last_seen(last_seen_file, latest_url)

        # Open post page
        safe_get(driver, latest_url, "YouTube community post page")
        time.sleep(4)

        # Expand text if needed
        click_read_more_if_present(driver)

        # Screenshot
        screenshot_name = f"{screenshot_prefix}{timestamp()}.png"
        screenshot_path = str(Path(screenshot_name).resolve())

        ok = driver.get_full_page_screenshot_as_file(screenshot_path)

        if ok:
            print(time.strftime("%H:%M:%S", time.localtime()), ": Screenshot saved:", screenshot_name)
        else:
            print(time.strftime("%H:%M:%S", time.localtime()), ": Screenshot failed:", screenshot_name)

    finally:
        driver.quit()


# ---------------- MAIN ----------------

def main():
    capture_community_posts = False

    if len(sys.argv) < 3:
        usage()
        sys.exit(1)

    if len(sys.argv) == 4:
        capture_community_posts = True
        channel_posts_url = sys.argv[3]

    live_url = sys.argv[1]
    lolcow_name = sys.argv[2]
    time.strftime("%H:%M:%S", time.localtime())
    print("\n")
    print("__________________________________________________")
    print(f"Starting Lolcow Archiver for {lolcow_name}")
    print(f"Checking for livestream at {live_url}")
    if capture_community_posts:
        print (f"Checking for YouTube Community Posts at {channel_posts_url}")
    print("--------------------------------------------------")

    while True:
        try:
            if capture_community_posts:
                check_for_new_post(lolcow_name, channel_posts_url)
            check_for_livestream(live_url)

        except Exception as e:
            print("ERROR:", e)

        if capture_community_posts and NEW_POST_COUNT > 0:
            print("\n")
            print("**************************************************")
            print(f"THERE ARE {NEW_POST_COUNT} NEW COMMUNITY POSTS FOR YOU TO ARCHIVE")
            print("**************************************************")

        if NEW_STREAM_COUNT > 0:
            print("\n")
            print("**************************************************")
            print(f"THERE ARE {NEW_STREAM_COUNT} NEW STREAMS FOR YOU TO ARCHIVE")
            print("**************************************************")

        print("\n")
        print(time.strftime("%H:%M:%S", time.localtime()), ": Sleeping for 30 seconds before checking again...\n")
        time.sleep(30)


if __name__ == "__main__":
    main()

Also, to automatically start up the script for a selection of lolcows, here is an example batch of commands that I would run (the equivalent commands, with substituted path/script naming for my filesystem):
Code:
wt -w 0 nt --title "Kiss Alice" --suppressApplicationTitle -p "Kiss Alice" cmd /k "cd C:\PATH\TO\TEST_archiver-1-1 && python lolcow_archiver_1_1.py https://www.youtube.com/@BaiserAlice/live KissAlice https://www.youtube.com/@BaiserAlice/posts";
wt -w 0 nt --title "Glass" --suppressApplicationTitle -p "Glass" cmd /k "cd C:\PATH\TO\TEST_archiver-1-1 && python lolcow_archiver_1_1.py https://www.youtube.com/@GlassWindow11/live Glass https://www.youtube.com/@GlassWindow11/posts";
wt -w 0 nt --title "UrghBla" --suppressApplicationTitle -p "UrghBla" cmd /k "cd C:\PATH\TO\TEST_archiver-1-1 && python lolcow_archiver_1_1.py https://www.youtube.com/@UrghBla/live UrghBla https://www.youtube.com/@UrghBla/posts";
wt -w 0 nt --title "PWR" --suppressApplicationTitle -p "PWR" cmd /k "cd C:\PATH\TO\TEST_archiver-1-1 && python lolcow_archiver_1_1.py https://kick.com/pwrworld/ PWR https://www.youtube.com/@PWRWorldOfficial/posts";
echo DONE;

Resulting in following command line window with tabs for each script executing per lolcow being monitored:
lolcow_archiver_batch_script_result.png
 
Late reply.
- Archive.today has always raped you with captchas. This problem isn't new.
Since when? Ever since I have used the service, I have only gotten a reCAPTCHA when trying trying to archive a webpage, nothing else.
- What are you trying to archive? This problem could be site specific
I don't recall any specifics but I think some things I've tried to archive were:
- KF homepage
- old.reddit.com thread
- An account on Xitter
I already know that the successful archival of 2 of these (KF and Xitter) vary wildly but the bottom line is that I was at least able to get some progress going which hasn't been the case for a bit.
Check your browser settings to see if DNS over HTTPS is enabled—if it is, try disabling it or switching your DNS provider to Cloudflare or Google. If the site is still down, try accessing it through its onion link (archiveiya74codqgiixo33q62qlrqtkgmcitqx5u2oeqnmn5bpcbiyd.onion), Also, as a quality-of-life tip, you can use a CAPTCHA-solving tool like Buster to make the process smoother.
The last time I was able to test, I actually found out that I was having a fair bit of issues with DNS-over-HTTPS using Mullvad's default url (https://dns.mullvad.net/dns-query) with websites for some reason not loading the first time or at all even though I've used it since forever and never had problems with it. I've switched to Cloudflare's for the time being but it didn't seem to make a difference for archive.today.

I'll try again when I'm in a better position to do so and try out the .onion link.
 
The last time I was able to test, I actually found out that I was having a fair bit of issues with DNS-over-HTTPS using Mullvad's default url (https://dns.mullvad.net/dns-query) with websites for some reason not loading the first time or at all even though I've used it since forever and never had problems with it. I've switched to Cloudflare's for the time being but it didn't seem to make a difference for archive.today.

I'll try again when I'm in a better position to do so and try out the .onion link.
Cloudflare and archive.today had a weird years long DNS issue preventing 1.1.1.1 users from accessing archive.today. Both parties blamed each other. This isn't mentioned on the wikipedia article because some random faggot decided the issue "seems to be fixed" (good for you retarded wikipedo) and no one has bothered to revert that edit.
I don't use Cloudflare's DNS when connecting to archive.today for this reason.
 
I feel like the OP needs an update/refresher since yt-dl went through that whole DMCA arc a few years ago and came out victorious the other end as yt-dlp. If @Osama Bands Laden is still on his OP rewrite bender that'd be an important one to tackle :)

Also there are now mobile apps (android) available that leverage yt-dlp and ffmpeg, which may help pointing the type of people that go for the phonefag excuse, towards the light, when it comes to archiving.

Notable example:
https://github.com/deniscerri/ytdlnis

Given how OP was born in 2014, mobilefagging was a limited thing when it came to browsing forums. But the times have been a-changin' and xenforo-sneedfork works reasonably well with the mobile UX in mind. I'd dare to say that a lot of changes made to the forums were designed with phonefags in mind.

Might be worth to put some energy back into the archivists' spirit of this sites underbelly.

@Null

edit // addendum:
Also reCAPTCHA is going to be _really_ fucking bad going forward, which is relevant with archival services such as archive.ph/.today.
They also ran into a controversy of tampering with archives some time back.
Just something to consider.
 
Last edited:
So does the New York Times not work with archive.ph anymore?
NYT and a bunch of other faggy "journalism" conglomerates are currently doing everything to stop any sort of archival service because they need to jew readers out of subscription money (and also to preserve the ability to edit articles from the past to word them better according to their investors' interests). The Internet Archive, along with "Fight For The Future Education Fund" (a), have started a petition (a) to ask these companies to stop fucking them over.
1780694635347.png
 
archive.ph (not archive.md or archive.is) was redirecting me to this page... (http://archive.ph/fz139/ Link no longer goes to the page) Was this happening to anyone else? I noticed it was very sluggish this morning, and when I went to archive something it brought me to this page. I'm using TOR.
1780843098632.png
DeepL translated it as:
Access to this website
has been blocked
by order of government authorities

You can view the reason for the block in the unified registry

Sign up for Interactive TV
and decide for yourself what to block!

Edit: Refreshed and the page disappeared. I didn't change my exit node.
 
Last edited:
Here's an online version of yt-dlp that I've been using recently with great success since functional video download sites are seemingly now a thing of the past. Helpful if you're away from your PC and need to quickly download a video/stream to archive. Downside is there's no command prompt and the options available are limited but it's quick and works well.

www.ezmdl.com
 
This website is great because it archives content before people delete it. However, the moment you link something directly, it can be taken down. It's important that your natural instinct should be to archive while also linking directly. With this thread, we will go over some ways to archive content such as links, media, and other forms of media preservation.

Web Archives​

It's important to archive links directly to prevent linkrot. There's 5 ways to do this:

1. archive.today (archive.is) is the preferred way of archiving data. It creates a full static backup of a website with all its resources (example). It archives most of the popular social media sites (such as YouTube, Twitter, etc) including ones behind captchas which other web archive sites usually fail to do. It primarily is a one-for-all archival tool.
  • archive.today does block certain VPN connections from connecting to archive.today often resulting in infinite loading times. Try using TOR for connections or choosing another provider/country to load it properly. (tor link here)
  • archive.today has multiple mirrors of the site. archive.is, .fo, .li, .vn, .ph, and .md belong to archive.today.
2. GhostArchive (ghostarchive.org) creates a full living backup of a website with all its resources. When you archive with GhostArchive, you can choose it with JavaScript, or Noscript if it doesn't work. However, you can only archive links that are less than 50MB. It doesn't work with websites that load a captcha beforehand. It's a good option if archive.today fails with must-login services like Twitter or Instagram.
3. Megalodon (megalodon.jp) is a Japanese archival site that has been around since 2005. It's another popular static webpage that works similar to archive.today. However, you should not archive content that contains dox/phonebook information or anything defamatory as these requests can often be taken down. This is covered in their FAQ page.
4. Internet Archive (web.archive.org) is one of the oldest but also most popular sites. However, while it creates full living backups, some URLs can be excluded from the site. The Internet Archive has excluded kiwifarms.net after #DropKiwifarms. You can find the full list here. Ideally, if you archive stuff with the Internet Archive, you should archive it with archive.today or GhostArchive as the Internet Archive takes down certain content depending on the domain. This is especially true if the person you are archiving owns that domain as they can exclude it.
5. Locally: Full page screenshots can be done with browser extensions or built-in tools. Modern Chrome and Brave can capture screenshots that are larger than the screen by using inspect element. You can take a Node screenshot on Chrome & Brave like this (or on Firefox you can take page wide screenshots by right clicking and pressing "take screenshot"):
1784322884667.png

Ideally, you should be using archive.today/megalodon.jp to archive websites. Another approach is utilizing content mirror sites which mirror or relay content from other (maybe login protected) websites:
  • When archiving Twitter links, use GhostArchive for efficiency. If it doesn't work, try using a Nitter proxy and archiving it with archive.today. You can also replace the username with an i (example: https://x.com/i/status/2032434574978847136) to get more information out of a tweet (such as a username change).
  • If you're archiving Google Documents, add /mobilebasic to then end of the link you are archiving. This allows the full document to be preserved. If the document you are archiving has multiple chapters/pages, then export all those and upload them locally.
  • You can archive links from Internet Archive on archive.today. It's advised to do this, especially with more sensitive links.
  • For LinkedIn & Instagram, use GhostArchive. For YouTube & Twitter, use archive.today. LinkedIn blocks certain archive sites, so you should local archive LinkedIn accounts.
  • With Steam links, archive their ID64 (example). There's a more in depth explanation here on archiving certain components (reviews, user content, community posts).
  • With YouTube links, archive the channel URL (example). Use Megalodon for archiving YouTube links (like community posts/videos) to get comments on a video (example) and you can also get a specific YouTube comments URL and archive it this way (you can achieve this by right clicking on the timestamp of the comment and copying the link).
  • Telegram links can be archived by archive.today using the /sneed/ parameter (example: https://t.me/s/kiwifarms). This will only work if the channel is public, not age-restricted, or region banned.
  • You can usually archive Reddit links using old.reddit.com but archive services might get network blocked. If this is the case, try using a Redlib instance (such as safereddit.com) and archive the link this way. Megalodon however archives Reddit links just fine. If you have a link to that hidden reply, it can archive it too.
If you encounter any more tips, feel free to share in this thread.

Hosting​

You should always want to host on the site. The upload limit is 1GB and most formats are supported. If your file is very large or very important, make a Talk to Staff thread or email null@kiwifarms.net and it will be archived to https://kiwifarms.net/archive - however you should find a way to host it in your post. However, using 3rd party websites is rarely a good idea unless you're actually trying to show people the URL and not its content.

Video Archives​

When it comes to archiving content from long videos (YouTube, Kick, Twitch, Instagram, etc), you should be using yt-dlp. yt-dlp is a feature-rich command-line audio/video downloader with support for thousands of sites. There's also a GUI version which is a lot easier to use if you are not technically knowledgeable. YouTube often tries to patch these tools, so if you run into problems, we have a yt-dlp thread and a YouTube General thread to help. PreserveTube (link) also exists to archive YouTube content as well.

For general media capture from popular websites (such as Twitter, Reddit, Bluesky, etc), you can use cobalt.tools. It's open source, very simple to use, and is one of the most useful web based tools currently out there. It's pretty simple for beginners who don't want to install anything, as you can just put in the link to the page you want to download and let it do its thing like so:
cobalttools.webp

Cobalt supports these services and also has settings which make it a lot easier to get content.
1784322921245.png 1784322924943.png

While it supports YouTube, YouTube archives are a special case and YouTube goes hard against these services. While people usually set up their own instances to bypass the YouTube filters, it is highly recommended that you should just use yt-dlp instead of using cobalt instances in the long run.

Clipping​

Clipping is very easy and is very simple to do. If you have video archives ready, it can be simple to clip videos. In this short 4 minute video, Null goes over on how to set up Kdenlive (free and open source) and how to easily clip and export into a proper video playable on all browsers.


For more technically advanced users, @Avenue has published a simple guide on how to properly record and clip videos/livestreams for threads. It's simple and uses ShareX and Avidemux (video editor) and is simple to learn. It's also worth nothing that media compression part is now done via the Media Processor and you can skip this part.

If you like to make animated images/gifs for humorous moments on stream, @Gaunt King Ithan Rilph goes over how to do it using ShareX:

Other​

For other forms of media that don't fall under any of these categories:
  • If you want to export a discord chat or server, use DiscordChatExporter. It is open source and allows you to export chats with Discord IDs along with messages and attachments which is useful. It should be noted that when exporting large servers/lots of messages, you may be banned by Discord for "platform manipulation" (for suspected scraping). There's currently an issue open with an attempt to fix this but try applying ratelimits or join from single use burner accounts.
  • You can search through Reddit archives using Arctic Shift.
  • You can use Clearsky for additional information about a Bluesky account (such as block lists, posts, labels, and general profile information).
  • If you are archiving content for the Live Talent board such as VODs, check to see if it's in the Ragtag Archive especially if it's from an agency.
  • Kemono archives various paywalled content (such as Patreon, Gumroad, SubscribeStar, DLSite, Afdian, Fantia, and Pixiv Fanbox). They also have a sister site for archiving OnlyFans/Fansly content. Kemono stopped importing in April and Pawchive was launched as a fix (primarily Patreon/Pixiv Fanbox). Kemono was also open source.
 
If you want to save live Twitch stream but VOD is deleted (some streamers do it during stream when nudity appears or watching movies) the twitch-dlp is a great tool. It also allows to download live stream from certain timestamps and until the stream ends; checking if streamer is live and starting downloading the stream when it starts. You can use twitchtracker.com links for the stream to download deleted VODs, but it usually works only some time after the stream ends.

But I still don't know how to achieve chat from ongoing live streams with deleted VODs especially to render later to add into video beside recording chat with OBS. TwitchDownloader has a way to save chat (and stream) and render it into video, but does not work with deleted VODs.
 
Should we follow suit with Wikipedia and abandon archive.today, what with archive.today now being known for modifying archived content or are we just not giving a fuck?

Edit: yeah I know I'm retarded, but what if something happens where our archives get fucked with?
 
Last edited:
Back
Top Bottom