A Python script can save your Reddit items to CSV and JSON, but it cannot by itself get around the limit on what Reddit displays. Listings are capped at around 1,000 items: PRAW can iterate over what the API provides, but it cannot retrieve saved items that have already fallen outside that listing.
To try to recover older posts, also start an official data request from a desktop browser at reddit.com/settings/data-request. Reddit says preparing the archive can take up to 30 days. The archive may include saved_posts.csv and saved_comments.csv; Reddit's guide describes them as lists of saved items. Don't assume they contain the post text: several analyses of exports describe rows containing an ID and a permalink.
Two routes, two different results
This tutorial uses PRAW to export to your computer what the saved listing still returns. The script creates two files: a JSON file, useful for preserving structured fields, and a CSV file, convenient for opening in a spreadsheet. If you're looking for saves older than the limit, the official request is the route worth trying in parallel, although Reddit does not explicitly confirm that the archive covers those items in every case.
flowchart TD A["Crear solicitud oficial"] --> B["Descargar archivo"] A --> C["Preparar acceso a PRAW"] C --> D["Leer guardados visibles"] D --> E["Escribir CSV y JSON"] B --> F["Comprobar filas y enlaces"] E --> F
1. Install PRAW and set up access
PRAW is the Python library that iterates over Reddit listings. Install it in the environment where you'll run the script:
python -m pip install praw
You'll need the credentials for a Reddit application. The DEV Community guide describes a script-type application and PRAW's username-and-password flow; Marqly warns that API access may require explicit approval. Make sure you're authorized to use it, and don't paste your credentials into the code. The following example reads them from the environment.
In a macOS or Linux terminal, replace the example values with your own. These commands affect only the current terminal session:
export REDDIT_CLIENT_ID="tu_client_id"
export REDDIT_CLIENT_SECRET="tu_client_secret"
export REDDIT_USERNAME="tu_usuario"
export REDDIT_PASSWORD="tu_contrasena"
export REDDIT_USER_AGENT="saved-export/1.0 by u/tu_usuario"
If your account uses two-factor authentication, PRAW expects you to append the six-digit code to the password, separated by a colon, according to the DEV Community guide. Don't save that value in a file you'll share.
2. Read your saves and generate both formats
Save this program as reddit_saved_export.py. It uses limit=None to ask PRAW for all available items in the listing; this does not mean Reddit will return an unlimited history. The code distinguishes comments from posts and leaves fields that don't exist for a given item type empty.
import csv
import json
import os
from datetime import datetime, timezone
import praw
# Las credenciales llegan desde variables de entorno.
reddit = praw.Reddit(
client_id=os.environ["REDDIT_CLIENT_ID"],
client_secret=os.environ["REDDIT_CLIENT_SECRET"],
username=os.environ["REDDIT_USERNAME"],
password=os.environ["REDDIT_PASSWORD"],
user_agent=os.environ["REDDIT_USER_AGENT"],
)
rows = []
for item in reddit.user.me().saved(limit=None):
is_comment = item.name.startswith("t1_")
title = getattr(item, "title", None) or getattr(item, "link_title", "") or ""
body = getattr(item, "selftext", None)
if body is None:
body = getattr(item, "body", "") or ""
rows.append({
"id": item.id,
"type": "comment" if is_comment else "post",
"title": title,
"subreddit": str(item.subreddit),
"author": str(item.author) if item.author else "",
"permalink": f"https://www.reddit.com{item.permalink}",
"url": getattr(item, "url", "") or "",
"created_utc": datetime.fromtimestamp(
item.created_utc, tz=timezone.utc
).isoformat(),
"score": item.score,
"body": body,
})
# JSON conserva los campos y el texto completo disponible.
with open("reddit_saved.json", "w", encoding="utf-8") as file:
json.dump(rows, file, ensure_ascii=False, indent=2)
# CSV puede abrirse en programas de hojas de cálculo.
fieldnames = [
"id", "type", "title", "subreddit", "author", "permalink",
"url", "created_utc", "score", "body",
]
with open("reddit_saved.csv", "w", encoding="utf-8", newline="") as file:
writer = csv.DictWriter(file, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(rows)
print(f"Exportados {len(rows)} elementos visibles.")
Run the program from the same terminal where you defined the variables:
python reddit_saved_export.py
Both files appear in the current directory. The text fields correspond to content that is still available and that Reddit returns for the item; the script does not create a copy of deleted posts. It also does not preserve a save date: the created_utc field corresponds to the item's creation date.
3. Check what was written
Before treating the files as a complete copy, verify that both formats can be read and compare the number of rows. This second program does not contact Reddit; it only checks the local files.
import csv
import json
from pathlib import Path
json_path = Path("reddit_saved.json")
csv_path = Path("reddit_saved.csv")
with json_path.open(encoding="utf-8") as file:
json_rows = json.load(file)
with csv_path.open(encoding="utf-8", newline="") as file:
csv_rows = list(csv.DictReader(file))
print(f"JSON: {len(json_rows)} elementos")
print(f"CSV: {len(csv_rows)} elementos")
print(f"Filas coincidentes: {len(json_rows) == len(csv_rows)}")
if json_rows:
print("Primer enlace:", json_rows[0]["permalink"])
If the count is close to 1,000, don't interpret that result as the total number of your historical saves. PRAW's documentation states that most Reddit listings have a maximum of 1,000 items and are delivered in pages of up to 100.
4. Try the official route for older history
From a desktop browser, sign in to the correct account and visit reddit.com/settings/data-request. Follow the form and, if it lets you select a date range, DEV Community recommends choosing the full history. Reddit says preparation can take up to 30 days; the download link may arrive in your Reddit inbox or, in some cases, at your verified email address.
When you download the archive, look for saved_posts.csv and saved_comments.csv. Stashr and Marqly describe these CSVs as lists of IDs and permalinks, without titles or text. Coverage of items that no longer appear in the listing isn't guaranteed: Reddit describes them as saved items, but does not explicitly confirm that the export will always exceed the limit. Count the rows and keep the original archive before transforming it.
Mistakes to avoid
limit=None does not remove the cap. It only asks PRAW to iterate through everything the listing allows. A longer loop or repeating the download won't make items that Reddit no longer provides through that route reappear.
Don't confuse the creation date with the date you saved something. The example exports created_utc, not a timestamp for the act of saving. And the official CSV may be just a set of links: if you need titles or text, the script retrieves them for items it can still read; it does not add them retroactively to the official export.
Finally, treat the files and credentials as private data. A saved-items listing may include content you wouldn't want to leave in a shared folder. Don't upload the file or publish your access variables.
The result is a local export of the saves visible when you run the script, plus an official request that may provide additional links. Keep both copies: PRAW offers more context for the current listing; the data request is the remaining option to check for older items.
Sources: DEV Community, PRAW, Stashr, Marqly