Migrating to PRAW 8
PRAW 8 completes the deprecation cycle started during the 7.x series. This guide covers
every removed or changed item, with examples showing how to update your code.
Python Version Support
PRAW 8 requires Python 3.10 or newer. Support for Python 3.8 and 3.9, both of which are
end-of-life, has been dropped, and support for Python 3.13 and 3.14 has been added.
user.me() in read-only mode
Calling reddit.user.me() in read_only mode previously returned None
with a deprecation warning. It now raises ReadOnlyException.
Old:
if reddit.user.me() is None:
print("Not authenticated")
New:
from praw.exceptions import ReadOnlyException
try:
reddit.user.me()
except ReadOnlyException:
print("Not authenticated")
Redditor.subreddit is a UserSubreddit
The subreddit attribute of Redditor is a UserSubreddit instance.
Its values are accessed as attributes; the dict interface has been removed.
Old:
title = redditor.subreddit["title"]
New:
title = redditor.subreddit.title
Link submissions with body text
The selftext and url arguments to Subreddit.submit() are no longer
mutually exclusive. When url is provided, selftext is used as optional
Markdown-formatted body text to accompany the link submission.
Subreddit.submit_image(), Subreddit.submit_video(), and
Subreddit.submit_gallery() also accept an optional selftext parameter.
One exception: combining inline_media with selftext for a url submission
raises an exception, because Reddit does not support inline media in body text for link
submissions.
Arguments that must be passed by keyword
The following arguments must now be passed by keyword:
Old modmail
Reddit retired the old modmail system, so Subreddit.mod.inbox,
Subreddit.mod.unread, Subreddit.mod.stream.unread, SubredditMessage.mute,
and SubredditMessage.unmute have been removed. Use the new modmail interface
instead.
Old:
for message in reddit.subreddit("test").mod.unread():
print(message.subject)
New:
for conversation in reddit.subreddit("test").modmail.conversations(state="new"):
print(conversation.subject)
To stream conversations, use SubredditModerationStream.modmail_conversations()
(subreddit.mod.stream.modmail_conversations()). Muting and unmuting users is
available on ModmailConversation via ModmailConversation.mute() and
ModmailConversation.unmute().
The after argument for conversations() has also been removed. To resume a
listing from a known conversation, pass after through params:
conversations = reddit.subreddit("test").modmail.conversations(params={"after": "2gmz"})
Token managers
The token_manager keyword argument to Reddit, along with
BaseTokenManager, FileTokenManager, and SQLiteTokenManager, has been
removed. Refresh tokens no longer rotate, so a static refresh_token can be provided
directly.
Old:
from praw.util.token_manager import FileTokenManager
reddit = praw.Reddit(..., token_manager=FileTokenManager("token.txt"))
New:
reddit = praw.Reddit(..., refresh_token="...")
See Working with Refresh Tokens for the complete guide to obtaining and using refresh tokens.
Removed without replacement
The following were removed because Reddit no longer supports the underlying endpoints or
features:
Reddit.random_subreddit, Subreddit.random, and Subreddit.random_rising —
Reddit removed the random subreddit and random submission endpoints.
Comment.award, Submission.award, and the gild aliases on
Comment, Redditor, and Submission — Reddit removed the
awards API.
Redditor.gilded, Subreddit.gilded, and Redditor.gildings — gilded listings
were removed along with the awards API.
Subreddits.search_by_topic — the endpoint has returned 404 since 2020.
Reddit.validate_on_submit — Reddit now always validates posts on submission, so
the setting no longer has any effect. Remove any assignments to it.
WebSocketException.original_exception.
InboxableMixin.unblock_subreddit.
The reset_timestamp key in the dictionary returned by limits() — the
remaining keys are remaining and used.