PRAW: The Python Reddit API Wrapper
PRAW’s documentation is organized into the following sections:
Documentation Conventions
Unless otherwise mentioned, all examples in this document assume the use of a script application. See Authenticating via OAuth for information on using installed applications and web applications.
Quick Start
In this section, we go over everything you need to know to start building scripts or bots using PRAW, the Python Reddit API Wrapper. It’s fun and easy. Let’s get started.
Prerequisites
- Python Knowledge:
You need to know at least a little Python to use PRAW. PRAW supports Python 3.7+. If you are stuck on a problem, r/learnpython is a great place to ask for help.
- Reddit Knowledge:
A basic understanding of how Reddit works is a must. In the event you are not already familiar with Reddit start at Reddit Help.
- Reddit Account:
A Reddit account is required to access Reddit’s API. Create one at reddit.com.
- Client ID & Client Secret:
These two values are needed to access Reddit’s API as a script application (see Authenticating via OAuth for other application types). If you don’t already have a client ID and client secret, follow Reddit’s First Steps Guide to create them.
- User Agent:
A user agent is a unique identifier that helps Reddit determine the source of network requests. To use Reddit’s API, you need a unique and descriptive user agent. The recommended format is
<platform>:<app ID>:<version string> (by u/<Reddit username>)
. For example,android:com.example.myredditapp:v1.2.3 (by u/kemitche)
. Read more about user agents at Reddit’s API wiki page.
With these prerequisites satisfied, you are ready to learn how to do some of the most common tasks with Reddit’s API.
Common Tasks
Obtain a Reddit
Instance
Warning
For the sake of brevity, the following examples pass authentication information via
arguments to praw.Reddit()
. If you do this, you need to be careful not to
reveal this information to the outside world if you share your code. It is
recommended to use a praw.ini file in order to keep your
authentication information separate from your code.
You need an instance of the Reddit
class to do anything with PRAW. There are
two distinct states a Reddit
instance can be in: read-only,
and authorized.
Read-only Reddit
Instances
To create a read-only Reddit
instance, you need three pieces of information:
Client ID
Client secret
User agent
You may choose to provide these by passing in three keyword arguments when calling the
initializer of the Reddit
class: client_id
, client_secret
,
user_agent
(see Configuring PRAW for other methods of providing this
information). For example:
import praw
reddit = praw.Reddit(
client_id="my client id",
client_secret="my client secret",
user_agent="my user agent",
)
Just like that, you now have a read-only Reddit
instance.
print(reddit.read_only)
# Output: True
With a read-only instance, you can do something like obtaining 10 “hot” submissions from
r/test
:
# continued from code above
for submission in reddit.subreddit("test").hot(limit=10):
print(submission.title)
# Output: 10 submissions
If you want to do more than retrieve public information from Reddit, then you need an
authorized Reddit
instance.
Note
In the above example we are limiting the results to 10
. Without the limit
parameter PRAW should yield as many results as it can with a single request. For
most endpoints this results in 100 items per request. If you want to retrieve as
many as possible pass in limit=None
.
Obtain a Subreddit
To obtain a Subreddit
instance, pass the subreddit’s name when calling
subreddit
on your Reddit
instance. For example:
# assume you have a praw.Reddit instance bound to variable `reddit`
subreddit = reddit.subreddit("redditdev")
print(subreddit.display_name)
# Output: redditdev
print(subreddit.title)
# Output: reddit development
print(subreddit.description)
# Output: a subreddit for discussion of ...
Obtain Submission
Instances from a Subreddit
Now that you have a Subreddit
instance, you can iterate through some of its
submissions, each bound to an instance of Submission
. There are several sorts
that you can iterate through:
controversial
gilded
hot
new
rising
top
Each of these methods will immediately return a ListingGenerator
, which is to
be iterated through. For example, to iterate through the first 10 submissions based on
the hot
sort for a given subreddit try:
# assume you have a Subreddit instance bound to variable `subreddit`
for submission in subreddit.hot(limit=10):
print(submission.title)
# Output: the submission's title
print(submission.score)
# Output: the submission's score
print(submission.id)
# Output: the submission's ID
print(submission.url)
# Output: the URL the submission points to or the submission's URL if it's a self post
Note
The act of calling a method that returns a ListingGenerator
does not
result in any network requests until you begin to iterate through the
ListingGenerator
.
You can create Submission
instances in other ways too:
# assume you have a praw.Reddit instance bound to variable `reddit`
submission = reddit.submission("39zje0")
print(submission.title)
# Output: reddit will soon only be available ...
# or
submission = reddit.submission(url="https://www.reddit.com/...")
Obtain Redditor
Instances
There are several ways to obtain a redditor (a Redditor
instance). Two of the
most common ones are:
via the
author
attribute of aSubmission
orComment
instancevia the
redditor()
method ofReddit
For example:
# assume you have a Submission instance bound to variable `submission`
redditor1 = submission.author
print(redditor1.name)
# Output: name of the redditor
# assume you have a praw.Reddit instance bound to variable `reddit`
redditor2 = reddit.redditor("bboe")
print(redditor2.link_karma)
# Output: u/bboe's karma
Obtain Comment
Instances
Submissions have a comments
attribute that is a CommentForest
instance.
That instance is iterable and represents the top-level comments of the submission by the
default comment sort (confidence
). If you instead want to iterate over all
comments as a flattened list you can call the list()
method on a
CommentForest
instance. For example:
# assume you have a praw.Reddit instance bound to variable `reddit`
top_level_comments = list(submission.comments)
all_comments = submission.comments.list()
Note
The comment sort order can be changed by updating the value of comment_sort
on
the Submission
instance prior to accessing comments
(see:
/api/set_suggested_sort for possible values).
For example to have comments sorted by new
try something like:
# assume you have a praw.Reddit instance bound to variable `reddit`
submission = reddit.submission("39zje0")
submission.comment_sort = "new"
top_level_comments = list(submission.comments)
As you may be aware there will periodically be MoreComments
instances
scattered throughout the forest. Replace those MoreComments
instances at any
time by calling replace_more()
on a CommentForest
instance. Calling
replace_more()
access comments
, and so must be done after comment_sort
is
updated. See Extracting comments with PRAW for an example.
Determine Available Attributes of an Object
If you have a PRAW object, e.g., Comment
, Message
,
Redditor
, or Submission
, and you want to see what attributes are
available along with their values, use the built-in vars()
function of python.
For example:
import pprint
# assume you have a praw.Reddit instance bound to variable `reddit`
submission = reddit.submission("39zje0")
print(submission.title) # to make it non-lazy
pprint.pprint(vars(submission))
Note the line where we print the title. PRAW uses lazy objects so that network requests
to Reddit’s API are only issued when information is needed. Here, before the print line,
submission
points to a lazy Submission
object. When we try to print its
title, additional information is needed, thus a network request is made, and the
instances ceases to be lazy. Outputting all the attributes of a lazy object will result
in fewer attributes than expected.
Installing PRAW
PRAW supports Python 3.7+. The recommended way to install PRAW is via pip
.
pip install praw
Note
Depending on your system, you may need to use pip3
to install packages for
Python 3.
Warning
Avoid using sudo
to install packages. Do you really trust this package?
For instructions on installing Python and pip see “The Hitchhiker’s Guide to Python” Installation Guides.
Updating PRAW
PRAW can be updated by running:
pip install --upgrade praw
Installing Older Versions
Older versions of PRAW can be installed by specifying the version number as part of the installation command:
pip install praw==3.6.0
Installing the Latest Development Version
Is there a feature that was recently merged into PRAW that you cannot wait to take advantage of? If so, you can install PRAW directly from GitHub like so:
pip install --upgrade https://github.com/praw-dev/praw/archive/master.zip
You can also directly clone a copy of the repository using git, like so:
pip install --upgrade git+https://github.com/praw-dev/praw.git
Authenticating via OAuth
PRAW supports all three types of applications that can be registered on Reddit. Those are:
Before you can use any one of these with PRAW, you must first register an application of the appropriate type on Reddit.
If your application does not require a user context, it is read-only.
PRAW supports the flows that each of these applications can use. The following table defines which application types can use which flows:
Application Type |
Script |
Web |
Installed |
---|---|---|---|
Default Flow |
|||
Alternative Flows |
|||
Warning
For the sake of brevity, the following examples pass authentication information via
arguments to Reddit
. If you do this, you need to be careful not to reveal
this information to the outside world if you share your code. It is recommended to
use a praw.ini file in order to keep your authentication
information separate from your code.
Password Flow
Password Flow is the simplest type of authentication flow to work with because no
callback process is involved in obtaining an access_token
.
While password flow applications do not involve a redirect URI, Reddit still
requires that you provide one when registering your script application –
http://localhost:8080
is a simple one to use.
In order to use a password flow application with PRAW you need four pieces of information:
- client_id:
The client ID is at least a 14-character string listed just under “personal use script” for the desired developed application
- client_secret:
The client secret is at least a 27-character string listed adjacent to
secret
for the application.- password:
The password for the Reddit account used to register the application.
- username:
The username of the Reddit account used to register the application.
With this information authorizing as username
using a password flow app is as
simple as:
reddit = praw.Reddit(
client_id="SI8pN3DSbt0zor",
client_secret="xaxkj7HNh8kwg8e5t4m6KvSrbTI",
password="1guiwevlfo00esyy",
user_agent="testscript by u/fakebot3",
username="fakebot3",
)
To verify that you are authenticated as the correct user run:
print(reddit.user.me())
The output should contain the same name as you entered for username
.
Note
If the following exception is raised, double-check your credentials, and ensure that that the username and password you are using are for the same user with which the application is associated:
OAuthException: invalid_grant error processing request
Two-Factor Authentication
A 2FA token can be used by joining it to the password with a colon:
reddit = praw.Reddit(
client_id="SI8pN3DSbt0zor",
client_secret="xaxkj7HNh8kwg8e5t4m6KvSrbTI",
password="1guiwevlfo00esyy:955413",
user_agent="testscript by u/fakebot3",
username="fakebot3",
)
However, for such an app there is little benefit to using 2FA. The token must be refreshed after one hour; therefore, the 2FA secret would have to be stored along with the rest of the credentials in order to generate the token, which defeats the point of having an extra credential beyond the password.
If you do choose to use 2FA, you must handle the prawcore.OAuthException
that will
be raised by API calls after one hour.
Code Flow
A code flow application is useful for two primary purposes:
You have an application and want to be able to access Reddit from your users’ accounts.
You have a personal-use script application and you either want to
limit the access one of your PRAW-based programs has to Reddit
avoid the hassle of 2FA (described above)
not pass your username and password to PRAW (and thus not keep it in memory)
When registering your application you must provide a valid redirect URI. If you are running a website you will want to enter the appropriate callback URL and configure that endpoint to complete the code flow.
If you aren’t actually running a website, you can follow the Working with Refresh Tokens tutorial to learn how to obtain and use the initial refresh token.
Whether or not you follow the Working with Refresh Tokens tutorial there are two processes involved in obtaining access or refresh tokens.
Implicit Flow
The implicit flow requires a similar instantiation of the Reddit
class as
done in Code Flow, however, the token is returned directly as part of the
redirect. For the implicit flow call url()
like so:
print(reddit.auth.url(scopes=["identity"], state="...", implicit=True))
Then use implicit()
to provide the authorization to the Reddit
instance.
Read-Only Mode
All application types support a read-only mode. Read-only mode provides access to Reddit
like a logged out user would see including the default subreddits in the
reddit.front
listings.
In the absence of a refresh_token
both Code Flow and Implicit Flow
applications start in the read-only mode. With such applications read-only mode
is disabled when authorize()
, or implicit()
are successfully called.
Password Flow applications start up with read-only mode disabled.
Read-only mode can be toggled via:
# Enable read-only mode
reddit.read_only = True
# Disable read-only mode (must have a valid authorization)
reddit.read_only = False
Application-Only Flows
The following flows are the read-only mode flows for Reddit applications
Application-Only (Client Credentials)
This is the default flow for read-only mode in script and web applications. The idea behind this is that Reddit can trust these applications as coming from a given developer, however the application requires no logged-in user context.
An installed application cannot use this flow, because Reddit requires a
client_secret
to be given if this flow is being used. In other words, installed
applications are not considered confidential clients.
Application-Only (Installed Client)
This is the default flow for read-only mode in installed applications. The idea
behind this is that Reddit might not be able to trust these applications as coming
from a given developer. This would be able to happen if someone other than the developer
can potentially replicate the client information and then pretend to be the application,
such as in installed applications where the end user could retrieve the client_id
.
Note
No benefit is really gained from this in script or web apps. The one exception is for when a script or web app has multiple end users, this will allow you to give Reddit the information needed in order to distinguish different users of your app from each other (as the supplied device ID should be a unique string per both device (in the case of a web app, server) and user (in the case of a web app, browser session).
Using a Saved Refresh Token
A saved refresh token can be used to immediately obtain an authorized instance of
Reddit
like so:
reddit = praw.Reddit(
client_id="SI8pN3DSbt0zor",
client_secret="xaxkj7HNh8kwg8e5t4m6KvSrbTI",
refresh_token="WeheY7PwgeCZj4S3QgUcLhKE5S2s4eAYdxM",
user_agent="testscript by u/fakebot3",
)
print(reddit.auth.scopes())
The output from the above code displays which scopes are available on the
Reddit
instance.
Note
Observe that redirect_uri
does not need to be provided in such cases. It is only
needed when url()
is used.
Configuring PRAW
Configuration Options
PRAW’s configuration options are broken down into the following categories:
All of these options can be provided in any of the ways mentioned in Configuring PRAW.
Basic Configuration Options
- check_for_updates:
When
true
, check for new versions of PRAW. When a newer version of PRAW is available a message is reported via standard error (default:true
).- user_agent:
(Required) A unique description of your application. The following format is recommended according to Reddit’s API Rules:
<platform>:<app ID>:<version string> (by u/<reddit username>)
.
OAuth Configuration Options
- client_id:
(Required) The OAuth client ID associated with your registered Reddit application. See Authenticating via OAuth for instructions on registering a Reddit application.
- client_secret:
The OAuth client secret associated with your registered Reddit application. This option is required for all application types, however, the value must be set to
None
for installed applications.- redirect_uri:
The redirect URI associated with your registered Reddit application. This field is unused for script applications and is only needed for both web applications, and installed applications when the
url()
method is used.- password:
The password of the Reddit account associated with your registered Reddit script application. This field is required for script applications, and PRAW assumes it is working with a script application by its presence.
- username:
The username of the Reddit account associated with your registered Reddit script application. This field is required for script applications, and PRAW assumes it is working with a script application by its presence.
Reddit Site Configuration Options
PRAW can be configured to work with instances of Reddit which are not hosted at reddit.com. The following options may need to be updated in order to successfully access a third-party Reddit site:
- comment_kind:
The type prefix for comments on the
Reddit
instance (default:t1_
).- message_kind:
The type prefix for messages on the
Reddit
instance (default:t4_
).- oauth_url:
The URL used to access the
Reddit
instance’s API (default:https://oauth.reddit.com
).- reddit_url:
The URL used to access the
Reddit
instance. PRAW assumes the endpoints for establishing OAuth authorization are accessible under this URL (default:https://www.reddit.com
).- redditor_kind:
The type prefix for redditors on the
Reddit
instance (default:t2_
).- short_url:
The URL used to generate short links on the
Reddit
instance (default:https://redd.it
).- submission_kind:
The type prefix for submissions on the
Reddit
instance (default:t3_
).- subreddit_kind:
The type prefix for subreddits on the
Reddit
instance (default:t5_
).
Miscellaneous Configuration Options
These are options that do not belong in another category, but still play a part in PRAW.
- check_for_async:
When
true
, check if PRAW is being ran in an asynchronous environment whenever a request is made. If so, a warning will be logged recommending the usage of Async PRAW (default:true
).- ratelimit_seconds:
Controls the maximum number of seconds PRAW will capture ratelimits returned in JSON data. Because this can be as high as 14 minutes, only ratelimits of up to 5 seconds are captured and waited on by default.
Note
PRAW sleeps for the ratelimit value plus 1 second.
See Ratelimits for more info.
- timeout:
Controls the amount of time PRAW will wait for a request from Reddit to complete before throwing an exception. By default, PRAW waits 16 seconds before throwing an exception.
- warn_comment_sort:
When
true
, log a warning when thecomment_sort
attribute of a submission is updated after_fetch()
has been called (default:true
).
Custom Configuration Options
Your application can utilize PRAW’s configuration system in order to provide its own custom settings.
For instance you might want to add an app_debugging: true
option to your
application’s praw.ini
file. To retrieve the value of this custom option from an
instance of Reddit
you can execute:
reddit.config.custom["app_debugging"]
Note
Custom PRAW configuration environment variables are not supported. You can directly
access environment variables via os.getenv
.
Configuration options can be provided to PRAW in one of three ways:
praw.ini Files
PRAW comes with a praw.ini
file in the package directory, and looks for user defined
praw.ini
files in a few other locations:
In the current working directory at the time
Reddit
is initialized.In the launching user’s config directory. This directory, if available, is detected in order as one of the following:
In the directory specified by the
XDG_CONFIG_HOME
environment variable on operating systems that define such an environment variable (some modern Linux distributions).In the directory specified by
$HOME/.config
if theHOME
environment variable is defined (Linux and Mac OS systems).In the directory specified by the
APPDATA
environment variable (Windows).Note
To check the values of the environment variables, you can open up a terminal (Terminal/Terminal.app/Command Prompt/Powershell) and echo the variables (replacing <variable> with the name of the variable):
MacOS/Linux:
echo "$<variable>"
Windows Command Prompt
echo "%<variable>%"
Powershell
Write-Output "$env:<variable>"
You can also view environment variables in Python:
import os print(os.environ.get("<variable>", ""))
Format of praw.ini
praw.ini
uses the INI file format, which
can contain multiple groups of settings separated into sections. PRAW refers to each
section as a site
. The default site, DEFAULT
, is provided in the package’s
praw.ini
file. This site defines the default settings for interaction with Reddit.
The contents of the package’s praw.ini
file are:
[DEFAULT]
# A boolean to indicate whether or not to check for package updates.
check_for_updates=True
# Object to kind mappings
comment_kind=t1
message_kind=t4
redditor_kind=t2
submission_kind=t3
subreddit_kind=t5
trophy_kind=t6
# The URL prefix for OAuth-related requests.
oauth_url=https://oauth.reddit.com
# The amount of seconds of ratelimit to sleep for upon encountering a specific type of 429 error.
ratelimit_seconds=5
# The URL prefix for regular requests.
reddit_url=https://www.reddit.com
# The URL prefix for short URLs.
short_url=https://redd.it
# The timeout for requests to Reddit in number of seconds
timeout=16
Warning
Avoid modifying the package’s praw.ini
file. Prefer instead to override its
values in your own praw.ini
file. You can even override settings of the
DEFAULT
site in user defined praw.ini
files.
Defining Additional Sites
In addition to the DEFAULT
site, additional sites can be configured in user defined
praw.ini
files. All sites inherit settings from the DEFAULT
site and can
override whichever settings desired.
Defining additional sites is a convenient way to store OAuth credentials for various accounts, or distinct OAuth applications. For example if you have three separate bots, you might create a site for each:
[bot1]
client_id=revokedpDQy3xZ
client_secret=revokedoqsMk5nHCJTHLrwgvHpr
password=invalidht4wd50gk
username=fakebot1
[bot2]
client_id=revokedcIqbclb
client_secret=revokedCClyu4FjVO77MYlTynfj
password=invalidzpiq8s59j
username=fakebot2
[bot3]
client_id=revokedSbt0zor
client_secret=revokedNh8kwg8e5t4m6KvSrbTI
password=invalidlfo00esyy
username=fakebot3
Choosing a Site
Site selection is done via the site_name
parameter to Reddit
. For example,
to use the settings defined for bot2
as shown above, initialize Reddit
like so:
reddit = praw.Reddit("bot2", user_agent="bot2 user agent")
Note
In the above example you can obviate passing user_agent
if you add the setting
user_agent=...
in the [bot2]
site definition.
A site can also be selected via a praw_site
environment variable. This approach has
precedence over the site_name
parameter described above.
Using Interpolation
By default PRAW doesn’t apply any interpolation on the config file but this can be
changed with the config_interpolation
parameter which can be set to “basic” or
“extended”.
This can be useful to separate the components of the user_agent
into individual
variables, for example:
[bot1]
bot_name=MyBot
bot_version=1.2.3
bot_author=MyUser
user_agent=script:%(bot_name)s:v%(bot_version)s (by u/%(bot_author)s)
This uses basic interpolation thus Reddit
need to be initialized as follows:
reddit = praw.Reddit("bot1", config_interpolation="basic")
Then the value of reddit.config.user_agent
will be "script:MyBot:v1.2.3 (by
u/MyUser)"
.
See Interpolation of values for details.
Warning
The configparser.ConfigParser
instance is cached internally at the class
level, it is shared across all instances of Reddit
and once set it’s not
overridden by future invocations.
Keyword Arguments to Reddit
Most of PRAW’s documentation will demonstrate configuring PRAW through the use of
keyword arguments when initializing instances of Reddit
. All of the
Configuration Options can be specified using a keyword argument of the same name.
For example, if we wanted to explicitly pass the information for bot3
defined in
the praw.ini custom site example without using the bot3
site, we would initialize Reddit
as:
reddit = praw.Reddit(
client_id="SI8pN3DSbt0zor",
client_secret="xaxkj7HNh8kwg8e5t4m6KvSrbTI",
password="1guiwevlfo00esyy",
user_agent="testscript by u/fakebot3",
username="fakebot3",
)
PRAW Environment Variables
The second-highest priority configuration options can be passed to a program via
environment variables prefixed with praw_
.
For example, you can invoke your script as follows:
praw_username=bboe praw_password=not_my_password python my_script.py
The username
and password
provided via environment variables will override any
values contained in a praw.ini
file, but not any variables passed in through
Reddit
.
All Configuration Options can be provided in this manner, except for custom options.
Environment variables have the highest priority, followed by keyword arguments to
Reddit
, and finally settings in praw.ini
files.
Using an HTTP or HTTPS proxy with PRAW
PRAW internally relies upon the requests package to handle HTTP requests. Requests
supports use of HTTP_PROXY
and HTTPS_PROXY
environment variables in order to
proxy HTTP and HTTPS requests respectively [ref].
Given that PRAW exclusively communicates with Reddit via HTTPS, only the HTTPS_PROXY
option should be required.
For example, if you have a script named prawbot.py
, the HTTPS_PROXY
environment
variable can be provided on the command line like so:
HTTPS_PROXY=http://localhost:3128 ./prawbot.py
Configuring a custom requests Session
PRAW uses requests to handle networking. If your use-case requires custom configuration, it is possible to configure a custom Session instance and then use it with PRAW.
For example, some networks use self-signed SSL certificates when connecting to HTTPS
sites. By default, this would raise an exception in requests. To use a self-signed SSL
certificate without an exception from requests, first export the certificate as a
.pem
file. Then configure PRAW like so:
import praw
from requests import Session
session = Session()
session.verify = "/path/to/certfile.pem"
reddit = praw.Reddit(
client_id="SI8pN3DSbt0zor",
client_secret="xaxkj7HNh8kwg8e5t4m6KvSrbTI",
password="1guiwevlfo00esyy",
requestor_kwargs={"session": session}, # pass the custom Session instance
user_agent="testscript by u/fakebot3",
username="fakebot3",
)
The code above creates a custom Session instance and configures it to use a custom
certificate, then
passes it as a parameter when creating the Reddit
instance. Note that the
example above uses a Password Flow authentication type, but this method will work
for any authentication type.
Running Multiple Instances of PRAW
PRAW, as of version 4, performs rate limiting dynamically based on the HTTP response headers from Reddit. As a result you can safely run a handful of PRAW instances without any additional configuration.
Note
Running more than a dozen or so instances of PRAW concurrently may occasionally result in exceeding Reddit’s rate limits as each instance can only guess how many other instances are running.
If you are authorized on other users’ behalf, each authorization should have its own rate limit, even when running from a single IP address.
Discord Bots and Asynchronous Environments
If you plan on using PRAW in an asynchronous environment, (e.g., discord.py, asyncio) it is strongly recommended to use Async PRAW. It is the official asynchronous version of PRAW and its usage is similar and has the same features as PRAW.
Note
By default, PRAW will check to see if it is in an asynchronous environment every
time a network request is made. To disable this check, set the check_for_async
configuration option to False
. For example:
import praw
reddit = praw.Reddit(..., check_for_async=False)
Multiple Programs
The recommended way to run multiple instances of PRAW is to simply write separate independent Python programs. With this approach one program can monitor a comment stream and reply as needed, and another program can monitor a submission stream, for example.
If these programs need to share data consider using a third-party system such as a database or queuing system.
Multiple Threads
Warning
PRAW is not thread safe.
In a nutshell, instances of Reddit
are not thread-safe for a number of reasons
in its own code and each instance depends on an instance of requests.Session
, which
is not thread-safe [ref].
In theory, having a unique Reddit
instance for each thread, and making sure
that the instances are used in their respective threads only, will work.
Process
has been confirmed to work with PRAW, so that is a
viable choice as well. However, there are various errors with
Pool
, thus it is not supported by PRAW. Please use
ThreadPool
as an alternative to a process pool.
Please see this discussion and this GitHub issue for more information.
Logging in PRAW
It is occasionally useful to observe the HTTP requests that PRAW is issuing. To do so you have to configure and enable logging.
Add the following to your code to log everything available:
import logging
handler = logging.StreamHandler()
handler.setLevel(logging.DEBUG)
for logger_name in ("praw", "prawcore"):
logger = logging.getLogger(logger_name)
logger.setLevel(logging.DEBUG)
logger.addHandler(handler)
When properly configured, HTTP requests that are issued should produce output similar to the following:
Fetching: GET https://oauth.reddit.com/api/v1/me
Data: None
Params: {'raw_json': 1}
Response: 200 (876 bytes)
Furthermore, any API ratelimits from POST actions that are handled will produce a log entry with a message similar to the following message:
Rate limit hit, sleeping for 5.5 seconds
For more information on logging, see logging.Logger
.
Ratelimits
Even though PRAW respects the X-Ratelimit-*
headers and waits the appropriate time between
requests, there are other unknown ratelimits that Reddit has that might require
additional wait time (anywhere from milliseconds to minutes) for things such as
commenting, editing comments/posts, banning users, adding moderators, etc. PRAW will
sleep and try the request again if the requested wait time (as much as 600 seconds) is
less than or equal to PRAW’s ratelimit_seconds
configuration setting (default:
5s), PRAW will wait for the requested time
plus 1 second. If the requested wait time exceeds the set value of
ratelimit_seconds
, PRAW will raise RedditAPIException
.
For example, given the following Reddit
instance:
import praw
reddit = praw.Reddit(..., ratelimit_seconds=300)
Let’s say your bot posts a comment to Reddit every 30 seconds and Reddit returns the
ratelimit error: "You're doing that too much. Try again in 3 minutes."
. PRAW will
wait for 181 seconds since 181 seconds is less than the configured ratelimit_seconds
of 300 seconds. However, if Reddit returns the ratelimit error: "You're doing that too
much. Try again in 6 minutes."
, PRAW will raise an exception since 360 seconds is
greater than the configured ratelimit_seconds
of 300 seconds.
Frequently Asked Questions
Q: How can I refresh a comment/subreddit/submission?
A: Directly calling the constructors will refresh the value:
reddit.comment(comment.id)
reddit.subreddit(subreddit.display_name)
reddit.submission(submission.id)
Q: Whenever I try to do anything, I get an invalid_grant
error. What is the cause?
A: This means that either you provided the wrong password and/or the account you are trying to sign in with has 2FA enabled, and as such, either needs a 2FA token or a refresh token to sign in. A refresh token is preferred, because then you will not need to enter a 2FA token in order to sign in, and the session will last for longer than an hour. Refer to Two-Factor Authentication and Working with Refresh Tokens in order to use the respective auth methods.
Q: Some options (like getting moderator logs from r/mod) keep on timing out. How can I extend the timeout?
A: Set the timeout config option or initialize Reddit
with a timeout of your
choosing. Another option is to construct a Subreddit
instance with a subset of
subreddits (concatenated with +
) that you want logs from like so:
reddit.subreddit("pics+LifeProTips")
Q: Help, I keep on getting redirected to /r/subreddit/login/
!
Q2: I keep on getting this exception:
prawcore.exceptions.Redirect: Redirect to /r/subreddit/login/ (You may be trying to perform a non-read-only action via a read-only instance.)
A: PRAW is most likely in read-only mode. This normally occurs when PRAW is
authenticated without a username and password or a refresh token. In order to perform
this action, the Reddit
instance needs to be authenticated. See
OAuth Configuration Options to see the available authentication methods.
Q: Help, searching for URLs keeps on redirecting me to /submit
!
Q2: I keep on getting this exception: prawcore.exceptions.Redirect: Redirect to
/submit
A: Reddit redirects URL searches to the submit page of the URL. To search for the URL,
prefix url:
to the url and surround the url in quotation marks.
For example, the code block:
reddit.subreddit("all").search("https://google.com")
Will become this code block:
reddit.subreddit("all").search('url:"https://google.com"')
The Reddit Instance
- class praw.Reddit(site_name: str | None = None, *, config_interpolation: str | None = None, requestor_class: Type[Requestor] | None = None, requestor_kwargs: Dict[str, Any] | None = None, token_manager: BaseTokenManager | None = None, **config_settings: str | bool | int | None)
The Reddit class provides convenient access to Reddit’s API.
Instances of this class are the gateway to interacting with Reddit’s API through PRAW. The canonical way to obtain an instance of this class is via:
import praw reddit = praw.Reddit( client_id="CLIENT_ID", client_secret="CLIENT_SECRET", password="PASSWORD", user_agent="USERAGENT", username="USERNAME", )
- __init__(site_name: str | None = None, *, config_interpolation: str | None = None, requestor_class: Type[Requestor] | None = None, requestor_kwargs: Dict[str, Any] | None = None, token_manager: BaseTokenManager | None = None, **config_settings: str | bool | int | None)
Initialize a
Reddit
instance.- Parameters:
site_name – The name of a section in your
praw.ini
file from which to load settings from. This parameter, in tandem with an appropriately configuredpraw.ini
, file is useful if you wish to easily save credentials for different applications, or communicate with other servers running Reddit. Ifsite_name
isNone
, then the site name will be looked for in the environment variablepraw_site
. If it is not found there, theDEFAULT
site will be used (default:None
).config_interpolation – Config parser interpolation type that will be passed to
Config
(default:None
).requestor_class – A class that will be used to create a requestor. If not set, use
prawcore.Requestor
(default:None
).requestor_kwargs – Dictionary with additional keyword arguments used to initialize the requestor (default:
None
).token_manager – When provided, the passed instance, a subclass of
BaseTokenManager
, will manage tokens via two callback functions. This parameter must be provided in order to work with refresh tokens (default:None
).
Additional keyword arguments will be used to initialize the
Config
object. This can be used to specify configuration settings during instantiation of theReddit
instance. For more details, please see Configuring PRAW.Required settings are:
client_id
client_secret
(for installed applications set this value toNone
)user_agent
The
requestor_class
andrequestor_kwargs
allow for customization of the requestorReddit
will use. This allows, e.g., easily adding behavior to the requestor or wrapping itsSession
in a caching layer. Example usage:import json import betamax import requests from prawcore import Requestor from praw import Reddit class JSONDebugRequestor(Requestor): def request(self, *args, **kwargs): response = super().request(*args, **kwargs) print(json.dumps(response.json(), indent=4)) return response my_session = betamax.Betamax(requests.Session()) reddit = Reddit( ..., requestor_class=JSONDebugRequestor, requestor_kwargs={"session": my_session} )
- auth
An instance of
Auth
.Provides the interface for interacting with installed and web applications.
See also
- comment(id: str | None = None, *, url: str | None = None)
Return a lazy instance of
Comment
.- Parameters:
id – The ID of the comment.
url – A permalink pointing to the comment.
- delete(path: str, *, data: Dict[str, str | Any] | bytes | IO | str | None = None, json: Dict[Any, Any] | None = None, params: str | Dict[str, str] | None = None) Any
Return parsed objects returned from a DELETE request to
path
.- Parameters:
path – The path to fetch.
data – Dictionary, bytes, or file-like object to send in the body of the request (default:
None
).json – JSON-serializable object to send in the body of the request with a Content-Type header of application/json (default:
None
). Ifjson
is provided,data
should not be.params – The query parameters to add to the request (default:
None
).
- domain(domain: str)
Return an instance of
DomainListing
.- Parameters:
domain – The domain to obtain submission listings for.
- drafts
An instance of
DraftHelper
.Provides the interface for working with
Draft
instances.For example, to list the currently authenticated user’s drafts:
drafts = reddit.drafts()
To create a draft on r/test run:
reddit.drafts.create(title="title", selftext="selftext", subreddit="test")
- front
An instance of
Front
.Provides the interface for interacting with front page listings. For example:
for submission in reddit.front.hot(): print(submission)
- get(path: str, *, params: str | Dict[str, str | int] | None = None)
Return parsed objects returned from a GET request to
path
.- Parameters:
path – The path to fetch.
params – The query parameters to add to the request (default:
None
).
- inbox
An instance of
Inbox
.Provides the interface to a user’s inbox which produces
Message
,Comment
, andSubmission
instances. For example, to iterate through comments which mention the authorized user run:for comment in reddit.inbox.mentions(): print(comment)
- info(*, fullnames: Iterable[str] | None = None, subreddits: Iterable[praw.models.Subreddit | str] | None = None, url: str | None = None) Generator[praw.models.Subreddit | praw.models.Comment | praw.models.Submission, None, None]
Fetch information about each item in
fullnames
,url
, orsubreddits
.- Parameters:
fullnames – A list of fullnames for comments, submissions, and/or subreddits.
subreddits – A list of subreddit names or
Subreddit
objects to retrieve subreddits from.url – A url (as a string) to retrieve lists of link submissions from.
- Returns:
A generator that yields found items in their relative order.
Items that cannot be matched will not be generated. Requests will be issued in batches for each 100 fullnames.
Note
For comments that are retrieved via this method, if you want to obtain its replies, you will need to call
refresh()
on the yieldedComment
.Note
When using the URL option, it is important to be aware that URLs are treated literally by Reddit’s API. As such, the URLs
"youtube.com"
and"https://www.youtube.com"
will provide a different set of submissions.
- live
An instance of
LiveHelper
.Provides the interface for working with
LiveThread
instances. At present only new live threads can be created.reddit.live.create(title="title", description="description")
- multireddit
An instance of
MultiredditHelper
.Provides the interface to working with
Multireddit
instances. For example, you can obtain aMultireddit
instance via:reddit.multireddit(redditor="samuraisam", name="programming")
- notes
An instance of
RedditModNotes
.Provides the interface for working with
ModNote
s for multiple redditors across multiple subreddits.Note
The authenticated user must be a moderator of the provided subreddit(s).
For example, the latest note for u/spez in r/redditdev and r/test, and for u/bboe in r/redditdev can be iterated through like so:
redditor = reddit.redditor("bboe") subreddit = reddit.subreddit("redditdev") pairs = [(subreddit, "spez"), ("test", "spez"), (subreddit, redditor)] for note in reddit.notes(pairs=pairs): print(f"{note.label}: {note.note}")
- patch(path: str, *, data: Dict[str, str | Any] | bytes | IO | str | None = None, json: Dict[Any, Any] | None = None) Any
Return parsed objects returned from a PATCH request to
path
.- Parameters:
path – The path to fetch.
data – Dictionary, bytes, or file-like object to send in the body of the request (default:
None
).json – JSON-serializable object to send in the body of the request with a Content-Type header of application/json (default:
None
). Ifjson
is provided,data
should not be.
- post(path: str, *, data: Dict[str, str | Any] | bytes | IO | str | None = None, files: Dict[str, IO] | None = None, json: Dict[Any, Any] | None = None, params: str | Dict[str, str] | None = None) Any
Return parsed objects returned from a POST request to
path
.- Parameters:
path – The path to fetch.
data – Dictionary, bytes, or file-like object to send in the body of the request (default:
None
).files – Dictionary, filename to file (like) object mapping (default:
None
).json – JSON-serializable object to send in the body of the request with a Content-Type header of application/json (default:
None
). Ifjson
is provided,data
should not be.params – The query parameters to add to the request (default:
None
).
- put(path: str, *, data: Dict[str, str | Any] | bytes | IO | str | None = None, json: Dict[Any, Any] | None = None)
Return parsed objects returned from a PUT request to
path
.- Parameters:
path – The path to fetch.
data – Dictionary, bytes, or file-like object to send in the body of the request (default:
None
).json – JSON-serializable object to send in the body of the request with a Content-Type header of application/json (default:
None
). Ifjson
is provided,data
should not be.
- random_subreddit(*, nsfw: bool = False) praw.models.Subreddit
Return a random lazy instance of
Subreddit
.- Parameters:
nsfw – Return a random NSFW (not safe for work) subreddit (default:
False
).
- redditor(name: str | None = None, *, fullname: str | None = None) praw.models.Redditor
Return a lazy instance of
Redditor
.- Parameters:
name – The name of the redditor.
fullname – The fullname of the redditor, starting with
t2_
.
Either
name
orfullname
can be provided, but not both.
- redditors
An instance of
Redditors
.Provides the interface for
Redditor
discovery. For example, to iterate over the newest Redditors, run:for redditor in reddit.redditors.new(limit=None): print(redditor)
- request(*, data: Dict[str, str | Any] | bytes | IO | str | None = None, files: Dict[str, IO] | None = None, json: Dict[Any, Any] | None = None, method: str, params: str | Dict[str, str | int] | None = None, path: str) Any
Return the parsed JSON data returned from a request to URL.
- Parameters:
data – Dictionary, bytes, or file-like object to send in the body of the request (default:
None
).files – Dictionary, filename to file (like) object mapping (default:
None
).json – JSON-serializable object to send in the body of the request with a Content-Type header of application/json (default:
None
). Ifjson
is provided,data
should not be.method – The HTTP method (e.g.,
"GET"
,"POST"
,"PUT"
,"DELETE"
).params – The query parameters to add to the request (default:
None
).path – The path to fetch.
- submission(id: str | None = None, *, url: str | None = None) praw.models.Submission
Return a lazy instance of
Submission
.- Parameters:
id – A Reddit base36 submission ID, e.g.,
"2gmzqe"
.url – A URL supported by
Submission.id_from_url()
.
Either
id
orurl
can be provided, but not both.
- subreddit
An instance of
SubredditHelper
.Provides the interface to working with
Subreddit
instances. For example to create aSubreddit
run:reddit.subreddit.create(name="coolnewsubname")
To obtain a lazy
Subreddit
instance run:reddit.subreddit("test")
Multiple subreddits can be combined and filtered views of r/all can also be used just like a subreddit:
reddit.subreddit("redditdev+learnpython+botwatch") reddit.subreddit("all-redditdev-learnpython")
- subreddits
An instance of
Subreddits
.Provides the interface for
Subreddit
discovery. For example, to iterate over the set of default subreddits run:for subreddit in reddit.subreddits.default(limit=None): print(subreddit)
- user
An instance of
User
.Provides the interface to the currently authorized
Redditor
. For example to get the name of the current user run:print(reddit.user.me())
- username_available(name: str) bool
Check to see if the username is available.
For example, to check if the username
bboe
is available, try:reddit.username_available("bboe")
- property validate_on_submit: bool
Get validate_on_submit.
Deprecated since version 7.0: If property
validate_on_submit
is set toFalse
, the behavior is deprecated by Reddit. This attribute will be removed around May-June 2020.
reddit.live
- class praw.models.DraftHelper(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Provide a set of functions to interact with
Draft
instances.Note
The methods provided by this class will only work on the currently authenticated user’s
Draft
s.- __call__(draft_id: str | None = None) List[praw.models.Draft] | praw.models.Draft
Return a list of
Draft
instances.- Parameters:
draft_id – When provided, return
Draft
instance (default:None
).- Returns:
A
Draft
instance ifdraft_id
is provided. Otherwise, a list ofDraft
objects.
Note
Drafts fetched using a specific draft ID are lazily loaded, so you might have to access an attribute to get all the expected attributes.
This method can be used to fetch a specific draft by ID, like so:
draft_id = "124862bc-e1e9-11eb-aa4f-e68667a77cbb" draft = reddit.drafts(draft_id) print(draft)
- __init__(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Initialize a
PRAWBase
instance.- Parameters:
reddit – An instance of
Reddit
.
- create(*, flair_id: str | None = None, flair_text: str | None = None, is_public_link: bool = False, nsfw: bool = False, original_content: bool = False, selftext: str | None = None, send_replies: bool = True, spoiler: bool = False, subreddit: str | praw.models.Subreddit | praw.models.UserSubreddit | None = None, title: str | None = None, url: str | None = None, **draft_kwargs) praw.models.Draft
Create a new
Draft
.- Parameters:
flair_id – The flair template to select (default:
None
).flair_text – If the template’s
flair_text_editable
value isTrue
, this value will set a custom text (default:None
).flair_id
is required whenflair_text
is provided.is_public_link – Whether to enable public viewing of the draft before it is submitted (default:
False
).nsfw – Whether the draft should be marked NSFW (default:
False
).original_content – Whether the submission should be marked as original content (default:
False
).selftext – The Markdown formatted content for a text submission draft. Use
None
to make a title-only submission draft (default:None
).selftext
can not be provided ifurl
is provided.send_replies – When
True
, messages will be sent to the submission author when comments are made to the submission (default:True
).spoiler – Whether the submission should be marked as a spoiler (default:
False
).subreddit – The subreddit to create the draft for. This accepts a subreddit display name,
Subreddit
object, orUserSubreddit
object. IfNone
, theUserSubreddit
of currently authenticated user will be used (default:None
).title – The title of the draft (default:
None
).url – The URL for a
link
submission draft (default:None
).url
can not be provided ifselftext
is provided.
Additional keyword arguments can be provided to handle new parameters as Reddit introduces them.
- Returns:
The new
Draft
object.
reddit.front
- class praw.models.Front(reddit: praw.Reddit)
Front is a Listing class that represents the front page.
- __init__(reddit: praw.Reddit)
Initialize a
Front
instance.
- best(**generator_kwargs: str | int) Iterator[praw.models.Submission]
Return a
ListingGenerator
for best items.Additional keyword arguments are passed in the initialization of
ListingGenerator
.
- comments() CommentHelper
Provide an instance of
CommentHelper
.For example, to output the author of the 25 most recent comments of r/test execute:
for comment in reddit.subreddit("test").comments(limit=25): print(comment.author)
- controversial(*, time_filter: str = 'all', **generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for controversial items.- Parameters:
time_filter – Can be one of:
"all"
,"day"
,"hour"
,"month"
,"week"
, or"year"
(default:"all"
).- Raises:
ValueError
iftime_filter
is invalid.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").controversial(time_filter="week") reddit.multireddit(redditor="samuraisam", name="programming").controversial( time_filter="day" ) reddit.redditor("spez").controversial(time_filter="month") reddit.redditor("spez").comments.controversial(time_filter="year") reddit.redditor("spez").submissions.controversial(time_filter="all") reddit.subreddit("all").controversial(time_filter="hour")
- gilded(**generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for gilded items.Additional keyword arguments are passed in the initialization of
ListingGenerator
.For example, to get gilded items in r/test:
for item in reddit.subreddit("test").gilded(): print(item.id)
- hot(**generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for hot items.Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").hot() reddit.multireddit(redditor="samuraisam", name="programming").hot() reddit.redditor("spez").hot() reddit.redditor("spez").comments.hot() reddit.redditor("spez").submissions.hot() reddit.subreddit("all").hot()
- new(**generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for new items.Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").new() reddit.multireddit(redditor="samuraisam", name="programming").new() reddit.redditor("spez").new() reddit.redditor("spez").comments.new() reddit.redditor("spez").submissions.new() reddit.subreddit("all").new()
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit) Any
Return an instance of
cls
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.
- random_rising(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Submission]
Return a
ListingGenerator
for random rising submissions.Additional keyword arguments are passed in the initialization of
ListingGenerator
.For example, to get random rising submissions for r/test:
for submission in reddit.subreddit("test").random_rising(): print(submission.title)
- rising(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Submission]
Return a
ListingGenerator
for rising submissions.Additional keyword arguments are passed in the initialization of
ListingGenerator
.For example, to get rising submissions for r/test:
for submission in reddit.subreddit("test").rising(): print(submission.title)
- top(*, time_filter: str = 'all', **generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for top items.- Parameters:
time_filter – Can be one of:
"all"
,"day"
,"hour"
,"month"
,"week"
, or"year"
(default:"all"
).- Raises:
ValueError
iftime_filter
is invalid.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").top(time_filter="week") reddit.multireddit(redditor="samuraisam", name="programming").top(time_filter="day") reddit.redditor("spez").top(time_filter="month") reddit.redditor("spez").comments.top(time_filter="year") reddit.redditor("spez").submissions.top(time_filter="all") reddit.subreddit("all").top(time_filter="hour")
reddit.inbox
- class praw.models.Inbox(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Inbox is a Listing class that represents the inbox.
- __init__(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Initialize a
PRAWBase
instance.- Parameters:
reddit – An instance of
Reddit
.
- all(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Message | praw.models.Comment]
Return a
ListingGenerator
for all inbox comments and messages.Additional keyword arguments are passed in the initialization of
ListingGenerator
.To output the type and ID of all items available via this listing do:
for item in reddit.inbox.all(limit=None): print(repr(item))
- collapse(items: List[praw.models.Message])
Mark an inbox message as collapsed.
- Parameters:
items – A list containing instances of
Message
.
Requests are batched at 25 items (reddit limit).
For example, to collapse all unread Messages, try:
from praw.models import Message unread_messages = [] for item in reddit.inbox.unread(limit=None): if isinstance(item, Message): unread_messages.append(item) reddit.inbox.collapse(unread_messages)
See also
- comment_replies(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Comment]
Return a
ListingGenerator
for comment replies.Additional keyword arguments are passed in the initialization of
ListingGenerator
.To output the author of one request worth of comment replies try:
for reply in reddit.inbox.comment_replies(): print(reply.author)
- mark_all_read()
Mark all messages as read with just one API call.
Example usage:
reddit.inbox.mark_all_read()
Note
This method returns after Reddit acknowledges your request, instead of after the request has been fulfilled.
- mark_read(items: List[praw.models.Comment | praw.models.Message])
Mark Comments or Messages as read.
- Parameters:
items – A list containing instances of
Comment
and/orMessage
to be marked as read relative to the authorized user’s inbox.
Requests are batched at 25 items (reddit limit).
For example, to mark all unread Messages as read, try:
from praw.models import Message unread_messages = [] for item in reddit.inbox.unread(limit=None): if isinstance(item, Message): unread_messages.append(item) reddit.inbox.mark_read(unread_messages)
See also
- mark_unread(items: List[praw.models.Comment | praw.models.Message])
Unmark Comments or Messages as read.
- Parameters:
items – A list containing instances of
Comment
and/orMessage
to be marked as unread relative to the authorized user’s inbox.
Requests are batched at 25 items (Reddit limit).
For example, to mark the first 10 items as unread try:
to_unread = list(reddit.inbox.all(limit=10)) reddit.inbox.mark_unread(to_unread)
- mentions(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Comment]
Return a
ListingGenerator
for mentions.A mention is
Comment
in which the authorized redditor is named in its body like u/spez.Additional keyword arguments are passed in the initialization of
ListingGenerator
.For example, to output the author and body of the first 25 mentions try:
for mention in reddit.inbox.mentions(limit=25): print(f"{mention.author}\\n{mention.body}\\n")
- message(message_id: str) praw.models.Message
Return a
Message
corresponding tomessage_id
.- Parameters:
message_id – The base36 ID of a message.
For example:
message = reddit.inbox.message("7bnlgu")
- messages(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Message]
Return a
ListingGenerator
for inbox messages.Additional keyword arguments are passed in the initialization of
ListingGenerator
.For example, to output the subject of the most recent 5 messages try:
for message in reddit.inbox.messages(limit=5): print(message.subject)
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit) Any
Return an instance of
cls
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.
- sent(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Message]
Return a
ListingGenerator
for sent messages.Additional keyword arguments are passed in the initialization of
ListingGenerator
.For example, to output the recipient of the most recent 15 messages try:
for message in reddit.inbox.sent(limit=15): print(message.dest)
- stream(**stream_options: str | int | Dict[str, str]) Iterator[praw.models.Message | praw.models.Comment]
Yield new inbox items as they become available.
Items are yielded oldest first. Up to 100 historical items will initially be returned.
Keyword arguments are passed to
stream_generator()
.For example, to retrieve all new inbox items, try:
for item in reddit.inbox.stream(): print(item)
- submission_replies(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Comment]
Return a
ListingGenerator
for submission replies.Additional keyword arguments are passed in the initialization of
ListingGenerator
.To output the author of one request worth of submission replies try:
for reply in reddit.inbox.submission_replies(): print(reply.author)
- uncollapse(items: List[praw.models.Message])
Mark an inbox message as uncollapsed.
- Parameters:
items – A list containing instances of
Message
.
Requests are batched at 25 items (reddit limit).
For example, to uncollapse all unread Messages, try:
from praw.models import Message unread_messages = [] for item in reddit.inbox.unread(limit=None): if isinstance(item, Message): unread_messages.append(item) reddit.inbox.uncollapse(unread_messages)
See also
- unread(*, mark_read: bool = False, **generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Message | praw.models.Comment]
Return a
ListingGenerator
for unread comments and messages.- Parameters:
mark_read – Marks the inbox as read (default:
False
).
Note
This only marks the inbox as read not the messages. Use
Inbox.mark_read()
to mark the messages.Additional keyword arguments are passed in the initialization of
ListingGenerator
.For example, to output the author of unread comments try:
from praw.models import Comment for item in reddit.inbox.unread(limit=None): if isinstance(item, Comment): print(item.author)
reddit.live
- class praw.models.LiveHelper(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Provide a set of functions to interact with
LiveThread
s.- __call__(id: str) praw.models.LiveThread
Return a new lazy instance of
LiveThread
.This method is intended to be used as:
livethread = reddit.live("ukaeu1ik4sw5")
- Parameters:
id – A live thread ID, e.g.,
ukaeu1ik4sw5
.
- __init__(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Initialize a
PRAWBase
instance.- Parameters:
reddit – An instance of
Reddit
.
- create(title: str, *, description: str | None = None, nsfw: bool = False, resources: str = None) praw.models.LiveThread
Create a new
LiveThread
.- Parameters:
title – The title of the new
LiveThread
.description – The new
LiveThread
’s description.nsfw – Indicate whether this thread is not safe for work (default:
False
).resources – Markdown formatted information that is useful for the
LiveThread
.
- Returns:
The new
LiveThread
object.
- info(ids: List[str]) Generator[praw.models.LiveThread, None, None]
Fetch information about each live thread in
ids
.- Parameters:
ids – A list of IDs for a live thread.
- Returns:
A generator that yields
LiveThread
instances.
Live threads that cannot be matched will not be generated. Requests will be issued in batches for each 100 IDs.
Warning
Unlike
Reddit.info()
, the output of this method may not reflect the order of input.Usage:
ids = ["3rgnbke2rai6hen7ciytwcxadi", "sw7bubeycai6hey4ciytwamw3a", "t8jnufucss07"] for thread in reddit.live.info(ids): print(thread.title)
- now() praw.models.LiveThread | None
Get the currently featured live thread.
- Returns:
The
LiveThread
object, orNone
if there is no currently featured live thread.
Usage:
thread = reddit.live.now() # LiveThread object or None
reddit.multireddit
- class praw.models.MultiredditHelper(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Provide a set of functions to interact with multireddits.
- __call__(*, name: str, redditor: str | praw.models.Redditor) praw.models.Multireddit
Return a lazy instance of
Multireddit
.- Parameters:
name – The name of the multireddit.
redditor – A redditor name or
Redditor
instance who owns the multireddit.
- __init__(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Initialize a
PRAWBase
instance.- Parameters:
reddit – An instance of
Reddit
.
- create(*, description_md: str | None = None, display_name: str, icon_name: str | None = None, key_color: str | None = None, subreddits: str | praw.models.Subreddit, visibility: str = 'private', weighting_scheme: str = 'classic') praw.models.Multireddit
Create a new
Multireddit
.- Parameters:
display_name – The display name for the new multireddit.
subreddits – Subreddits to add to the new multireddit. Can be a list of either
Subreddit
instances or subreddit display names.description_md – Description for the new multireddit, formatted in markdown.
icon_name – Can be one of:
"art and design"
,"ask"
,"books"
,"business"
,"cars"
,"comics"
,"cute animals"
,"diy"
,"entertainment"
,"food and drink"
,"funny"
,"games"
,"grooming"
,"health"
,"life advice"
,"military"
,"models pinup"
,"music"
,"news"
,"philosophy"
,"pictures and gifs"
,"science"
,"shopping"
,"sports"
,"style"
,"tech"
,"travel"
,"unusual stories"
,"video"
, orNone
.key_color – RGB hex color code of the form
"#FFFFFF"
.visibility – Can be one of:
"hidden"
,"private"
, or"public"
(default:"private"
).weighting_scheme – Can be one of:
"classic"
or"fresh"
(default:"classic"
).
- Returns:
The new
Multireddit
object.
reddit.redditors
- class praw.models.Redditors(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Redditors is a Listing class that provides various
Redditor
lists.- __init__(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Initialize a
PRAWBase
instance.- Parameters:
reddit – An instance of
Reddit
.
- new(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Subreddit]
Return a
ListingGenerator
for newRedditors
.Additional keyword arguments are passed in the initialization of
ListingGenerator
.
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit) Any
Return an instance of
cls
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.
- partial_redditors(ids: Iterable[str]) Iterator[PartialRedditor]
Get user summary data by redditor IDs.
- Parameters:
ids – An iterable of redditor fullname IDs.
- Returns:
A iterator producing
PartialRedditor
objects.
Each ID must be prefixed with
t2_
.Invalid IDs are ignored by the server.
- popular(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Subreddit]
Return a
ListingGenerator
for popularRedditors
.Additional keyword arguments are passed in the initialization of
ListingGenerator
.
- search(query: str, **generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Subreddit]
Return a
ListingGenerator
of Redditors forquery
.- Parameters:
query – The query string to filter Redditors by.
- Returns:
Redditor
s.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.
- stream(**stream_options: str | int | Dict[str, str]) Iterator[praw.models.Subreddit]
Yield new Redditors as they are created.
Redditors are yielded oldest first. Up to 100 historical Redditors will initially be returned.
Keyword arguments are passed to
stream_generator()
.
reddit.subreddit
- class praw.models.SubredditHelper(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Provide a set of functions to interact with Subreddits.
- __call__(display_name: str) praw.models.Subreddit
Return a lazy instance of
Subreddit
.- Parameters:
display_name – The name of the subreddit.
- __init__(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Initialize a
PRAWBase
instance.- Parameters:
reddit – An instance of
Reddit
.
- create(name: str, *, link_type: str = 'any', subreddit_type: str = 'public', title: str | None = None, wikimode: str = 'disabled', **other_settings: str | None) praw.models.Subreddit
Create a new
Subreddit
.- Parameters:
name – The name for the new subreddit.
link_type – The types of submissions users can make. One of
"any"
,"link"
, or"self"
(default:"any"
).subreddit_type – One of
"archived"
,"employees_only"
,"gold_only"
,"gold_restricted"
,"private"
,"public"
, or"restricted"
(default:"public"
).title – The title of the subreddit. When
None
or""
use the value ofname
.wikimode – One of
"anyone"
,"disabled"
, or"modonly"
(default:"disabled"
).
Any keyword parameters not provided, or set explicitly to
None
, will take on a default value assigned by the Reddit server.See also
update()
for documentation of other available settings.
reddit.subreddits
- class praw.models.Subreddits(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Subreddits is a Listing class that provides various subreddit lists.
- __init__(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Initialize a
PRAWBase
instance.- Parameters:
reddit – An instance of
Reddit
.
- default(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Subreddit]
Return a
ListingGenerator
for default subreddits.Additional keyword arguments are passed in the initialization of
ListingGenerator
.
- gold(**generator_kwargs) Iterator[praw.models.Subreddit]
Alias for
premium()
to maintain backwards compatibility.
- new(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Subreddit]
Return a
ListingGenerator
for new subreddits.Additional keyword arguments are passed in the initialization of
ListingGenerator
.
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit) Any
Return an instance of
cls
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.
- popular(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Subreddit]
Return a
ListingGenerator
for popular subreddits.Additional keyword arguments are passed in the initialization of
ListingGenerator
.
Return a
ListingGenerator
for premium subreddits.Additional keyword arguments are passed in the initialization of
ListingGenerator
.
- recommended(subreddits: List[str | praw.models.Subreddit], omit_subreddits: List[str | praw.models.Subreddit] | None = None) List[praw.models.Subreddit]
Return subreddits recommended for the given list of subreddits.
- search(query: str, **generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Subreddit]
Return a
ListingGenerator
of subreddits matchingquery
.Subreddits are searched by both their title and description.
- Parameters:
query – The query string to filter subreddits by.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.See also
search_by_name()
to search by subreddit names
- search_by_name(query: str, *, include_nsfw: bool = True, exact: bool = False) List[praw.models.Subreddit]
Return list of
Subreddit
s whose names begin withquery
.- Parameters:
query – Search for subreddits beginning with this string.
exact – Return only exact matches to
query
(default:False
).include_nsfw – Include subreddits labeled NSFW (default:
True
).
- search_by_topic(query: str) List[praw.models.Subreddit]
Return list of Subreddits whose topics match
query
.- Parameters:
query – Search for subreddits relevant to the search topic.
Note
As of 09/01/2020, this endpoint always returns 404.
- stream(**stream_options: str | int | Dict[str, str]) Iterator[praw.models.Subreddit]
Yield new subreddits as they are created.
Subreddits are yielded oldest first. Up to 100 historical subreddits will initially be returned.
Keyword arguments are passed to
stream_generator()
.
reddit.user
- class praw.models.User(reddit: praw.Reddit)
The
User
class provides methods for the currently authenticated user.- __init__(reddit: praw.Reddit)
Initialize an
User
instance.This class is intended to be interfaced with through
reddit.user
.
- blocked() List[praw.models.Redditor]
Return a
RedditorList
of blockedRedditor
s.
- contributor_subreddits(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Subreddit]
Return a
ListingGenerator
of contributorSubreddit
s.These are subreddits in which the user is an approved user.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.To print a list of the subreddits that you are an approved user in, try:
for subreddit in reddit.user.contributor_subreddits(limit=None): print(str(subreddit))
- friends(*, user: praw.models.Redditor | str | None = None) List[praw.models.Redditor] | praw.models.Redditor
Return a
RedditorList
of friends or aRedditor
in the friends list.- Parameters:
user – Checks to see if you are friends with the redditor. Either an instance of
Redditor
or a string can be given.- Returns:
A list of
Redditor
s, or a singleRedditor
ifuser
is specified. TheRedditor
instance(s) returned also has friend attributes.- Raises:
An instance of
RedditAPIException
if you are not friends with the specifiedRedditor
.
- karma() Dict[praw.models.Subreddit, Dict[str, int]]
Return a dictionary mapping
Subreddit
s to their karma.The returned dict contains subreddits as keys. Each subreddit key contains a sub-dict that have keys for
comment_karma
andlink_karma
. The dict is sorted in descending karma order.Note
Each key of the main dict is an instance of
Subreddit
. It is recommended to iterate over the dict in order to retrieve the values, preferably throughdict.items()
.
- me(*, use_cache: bool = True) praw.models.Redditor | None
Return a
Redditor
instance for the authenticated user.- Parameters:
use_cache – When
True
, and if this function has been previously called, returned the cached version (default:True
).
Note
If you change the
Reddit
instance’s authorization, you might want to refresh the cached value. Prefer using separateReddit
instances, however, for distinct authorizations.Deprecated since version 7.2: In
read_only
mode this method returnsNone
. In PRAW 8 this method will raiseReadOnlyException
when called inread_only
mode. To operate in PRAW 8 mode, set the config variablepraw8_raise_exception_on_me
toTrue
.
- moderator_subreddits(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Subreddit]
Return a
ListingGenerator
subreddits that the user moderates.Additional keyword arguments are passed in the initialization of
ListingGenerator
.To print a list of the names of the subreddits you moderate, try:
for subreddit in reddit.user.moderator_subreddits(limit=None): print(str(subreddit))
See also
- multireddits() List[praw.models.Multireddit]
Return a list of
Multireddit
s belonging to the user.
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit) Any
Return an instance of
cls
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.
- pin(submission: praw.models.Submission, *, num: int = None, state: bool = True)
Set the pin state of a submission on the authenticated user’s profile.
- Parameters:
submission – An instance of
Submission
that will be pinned/unpinned.num –
If specified, the slot in which the submission will be pinned into. If there is a submission already in the specified slot, it will be replaced. If
None
or there is not a submission in the specified slot, the first available slot will be used (default:None
). If all slots are used the following will occur:Old Reddit:
The submission in the last slot will be unpinned.
The remaining pinned submissions will be shifted down a slot.
The new submission will be pinned in the first slot.
New Reddit:
The submission in the first slot will be unpinned.
The remaining pinned submissions will be shifted up a slot.
The new submission will be pinned in the last slot.
Note
At the time of writing (10/22/2021), there are 4 pin slots available and pins are in reverse order on old Reddit. If
num
is an invalid value, Reddit will ignore it and the same behavior will occur as ifnum
isNone
.state –
True
pins the submission,False
unpins (default:True
).
- Raises:
prawcore.BadRequest
when pinning a removed or deleted submission.- Raises:
prawcore.Forbidden
when pinning a submission the authenticated user is not the author of.
submission = next(reddit.user.me().submissions.new()) reddit.user.pin(submission)
- preferences() praw.models.Preferences
Get an instance of
Preferences
.The preferences can be accessed as a
dict
like so:preferences = reddit.user.preferences() print(preferences["show_link_flair"])
Preferences can be updated via:
reddit.user.preferences.update(show_link_flair=True)
The
Preferences.update()
method returns the new state of the preferences as adict
, which can be used to check whether a change went through. Changes with invalid types or parameter names fail silently.original_preferences = reddit.user.preferences() new_preferences = reddit.user.preferences.update(invalid_param=123) print(original_preferences == new_preferences) # True, no change
- subreddits(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Subreddit]
Return a
ListingGenerator
ofSubreddit
s the user is subscribed to.Additional keyword arguments are passed in the initialization of
ListingGenerator
.To print a list of the subreddits that you are subscribed to, try:
for subreddit in reddit.user.subreddits(limit=None): print(str(subreddit))
- trusted() List[praw.models.Redditor]
Return a
RedditorList
of trustedRedditor
s.To display the usernames of your trusted users and the times at which you decided to trust them, try:
trusted_users = reddit.user.trusted() for user in trusted_users: print(f"User: {user.name}, time: {user.date}")
Working with PRAW’s Models
Comment
- class praw.models.Comment(reddit: praw.Reddit, id: str | None = None, url: str | None = None, _data: Dict[str, Any] | None = None)
A class that represents a Reddit comment.
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
author
Provides an instance of
Redditor
.body
The body of the comment, as Markdown.
body_html
The body of the comment, as HTML.
created_utc
Time the comment was created, represented in Unix Time.
distinguished
Whether or not the comment is distinguished.
edited
Whether or not the comment has been edited.
id
The ID of the comment.
is_submitter
Whether or not the comment author is also the author of the submission.
link_id
The submission ID that the comment belongs to.
parent_id
The ID of the parent comment (prefixed with
t1_
). If it is a top-level comment, this returns the submission ID instead (prefixed witht3_
).permalink
A permalink for the comment.
Comment
objects from the inbox have acontext
attribute instead.replies
Provides an instance of
CommentForest
.saved
Whether or not the comment is saved.
score
The number of upvotes for the comment.
stickied
Whether or not the comment is stickied.
submission
Provides an instance of
Submission
. The submission that the comment belongs to.subreddit
Provides an instance of
Subreddit
. The subreddit that the comment belongs to.subreddit_id
The subreddit ID that the comment belongs to.
- __init__(reddit: praw.Reddit, id: str | None = None, url: str | None = None, _data: Dict[str, Any] | None = None)
Initialize a
Comment
instance.
- award(*, gild_type: str = 'gid_2', is_anonymous: bool = True, message: str = None) dict
Award the author of the item.
- Parameters:
gild_type – Type of award to give. See table below for currently know global award types.
is_anonymous – If
True
, the authenticated user’s username will not be revealed to the recipient.message – Message to include with the award.
- Returns:
A dict containing info similar to what is shown below:
{ "subreddit_balance": 85260, "treatment_tags": [], "coins": 8760, "gildings": {"gid_1": 0, "gid_2": 1, "gid_3": 0}, "awarder_karma_received": 4, "all_awardings": [ { "giver_coin_reward": 0, "subreddit_id": None, "is_new": False, "days_of_drip_extension": 0, "coin_price": 75, "id": "award_9663243a-e77f-44cf-abc6-850ead2cd18d", "penny_donate": 0, "coin_reward": 0, "icon_url": "https://www.redditstatic.com/gold/awards/icon/SnooClappingPremium_512.png", "days_of_premium": 0, "icon_height": 512, "tiers_by_required_awardings": None, "icon_width": 512, "static_icon_width": 512, "start_date": None, "is_enabled": True, "awardings_required_to_grant_benefits": None, "description": "For an especially amazing showing.", "end_date": None, "subreddit_coin_reward": 0, "count": 1, "static_icon_height": 512, "name": "Bravo Grande!", "icon_format": "APNG", "award_sub_type": "PREMIUM", "penny_price": 0, "award_type": "global", "static_icon_url": "https://i.redd.it/award_images/t5_q0gj4/59e02tmkl4451_BravoGrande-Static.png", } ], }
Warning
Requires the authenticated user to own Reddit Coins. Calling this method will consume Reddit Coins.
To award the gold award anonymously do:
comment = reddit.comment("dkk4qjd") comment.award() submission = reddit.submission("8dmv8z") submission.award()
To award the platinum award with the message ‘Nice!’ and reveal your username to the recipient do:
comment = reddit.comment("dkk4qjd") comment.award(gild_type="gild_3", message="Nice!", is_anonymous=False) submission = reddit.submission("8dmv8z") submission.award(gild_type="gild_3", message="Nice!", is_anonymous=False)
This is a list of known global awards (as of 11/08/2021)
Name
Icon
Gild Type
Description
Cost
Silver
gid_1
Shows the Silver Award… and that’s it.
100
Gold
gid_2
Gives 100 Reddit Coins and a week of r/lounge access and ad-free browsing.
500
Platinum
gid_3
Gives 700 Reddit Coins and a month of r/lounge access and ad-free browsing.
1800
LOVE!
award_5eac457f-ebac-449b-93a7-eb17b557f03c
When you follow your heart, love is the answer
20
Starstruck
award_abb865cf-620b-4219-8777-3658cf9091fb
Can’t stop seeing stars
20
All-Seeing Upvote
award_b4ff447e-05a5-42dc-9002-63568807cfe6
A glowing commendation for all to see
30
Narwhal Salute
award_a2506925-fc82-4d6c-ae3b-b7217e09d7f0
A golden splash of respect
30
Wholesome Seal of Approval
award_c4b2e438-16bb-4568-88e7-7893b7662944
A glittering stamp for a feel-good thing
30
Ally
award_69c94eb4-d6a3-48e7-9cf2-0f39fed8b87c
Listen, get educated, and get involved.
50
Take My Energy
award_02d9ab2c-162e-4c01-8438-317a016ed3d9
I’m in this with you.
50
Wearing is Caring
award_80d4d339-95d0-43ac-b051-bc3fe0a9bab8
Keep the community and yourself healthy and happy.
50
Facepalm
award_b1b44fa1-8179-4d84-a9ed-f25bb81f1c5f
Lowers face into palm
70
Snek
award_99d95969-6100-45b2-b00c-0ec45ae19596
A smol, delicate danger noodle.
70
Tree Hug
award_b92370bb-b7de-4fb3-9608-c5b4a22f714a
Show nature some love.
70
Bravo Grande!
award_9663243a-e77f-44cf-abc6-850ead2cd18d
For an especially amazing showing.
75
Party Train
award_75f9bc56-eba3-4988-a1af-aec974404a0b
All aboard! Every five Party Train Awards gives the author 100 Reddit Coins and a week of r/lounge access and ad-free browsing. Rack up the awards and watch the train level-up!
75
Take My Power
award_92cb6518-a71a-4217-9f8f-7ecbd7ab12ba
Add my power to yours.
75
Defeated
award_58ef8551-8c27-4f03-afa5-748432194e3d
The process of taking a painful L
80
Hugz
award_8352bdff-3e03-4189-8a08-82501dd8f835
Everything is better with a good hug
80
‘MURICA
award_869d4135-8738-41e5-8630-de593b4f049f
Did somebody say ‘Murica?
100
Burning Cash
award_abcdefe4-c92f-4c66-880f-425962d17098
I don’t need it, I don’t even necessarily want it, but I’ve got some cash to burn so I’m gonna get it.
100
Dread
award_81cf5c92-8500-498c-9c94-3e4034cece0a
Staring into the abyss and it’s staring right back
100
Evil Cackle
award_483d8e29-bbe5-404e-a09a-c2d7b16c4fff
Laugh like a supervillain
100
Glow Up
award_01178870-6a4f-4172-8f36-9ed5092ee4f9
You look amazing, glowing, incredible!
100
Heartwarming
award_19860e30-3331-4bac-b3d1-bd28de0c7974
I needed this today
100
I am disappoint
award_03c4f93d-efc7-463b-98a7-c01814462ab0
I’m not mad, I’m just disappointed.
100
I’ll Drink to That
award_3267ca1c-127a-49e9-9a3d-4ba96224af18
Let’s sip to good health and good company
100
Keep Calm
award_1da6ff27-7c0d-4524-9954-86e5cda5fcac
Stop, chill, relax
100
Kiss
award_1e516e18-cbee-4668-b338-32d5530f91fe
You deserve a smooch
100
Lawyer Up
award_ae89e420-c4a5-47b8-a007-5dacf1c0f0d4
OBJECTION!
100
Masterpiece
award_b4072731-c0fb-4440-adc7-1063d6a5e6a0
C’est magnifique
100
Shocked
award_fbe9527a-adb3-430e-af1a-5fd3489e641b
I’m genuinely flabbergasted.
100
Tearing Up
award_43f3bf99-92d6-47ab-8205-130d26e7929f
This hits me right in the feels
100
Yummy
award_ae7f17fb-6538-4c75-9ff4-5f48b4cdaa94
That looks so good
100
Faith In Humanity Restored
award_611ff347-196b-4a14-ad4b-0076f2d8f9d2
This goes a long way to restore my faith in the people of Earth
125
Wholesome
award_5f123e3d-4f48-42f4-9c11-e98b566d5897
When you come across a feel-good thing.
125
Beating Heart
award_0d762fb3-17e4-4477-ab6b-9770b71b493c
My valentine makes my heart beat out of my chest.
150
Bless Up
award_77ba55a2-c33c-4351-ac49-807455a80148
Prayers up for the blessed.
150
Buff Doge
award_c42dc561-0b41-40b6-a23d-ef7e110e739e
So buff, wow
150
Cake
award_5fb42699-4911-42a2-884c-6fc8bdc36059
Did someone say… cake?
150
Helpful
award_f44611f1-b89e-46dc-97fe-892280b13b82
Thank you stranger. Shows the award.
150
I Shy
award_beccaae0-d745-44f9-bc5c-3c9f8117699b
No matter how hard I try, I’m too shy to confess my love!
150
Press F
award_88fdcafc-57a0-48db-99cc-76276bfaf28b
To pay respects.
150
Take My Money
award_a7f9cbd7-c0f1-4569-a913-ebf8d18de00b
I’m buying what you’re selling
150
2020 Veteran
award_f0875744-15da-41ee-8591-b88e5a88c430
A reward for making it through the most topsey- turvey year anyone can remember. Gives 100 coins to the recipient.
200
Baby Snoo
award_4d880932-4b45-4723-a964-5d749ace4df2
Baby Snoo is back and cuter than ever
200
Giggle
award_e813313c-1002-49bf-ac37-e966710f605f
Innocent laughter
200
Got the W
award_8dc476c7-1478-4d41-b940-f139e58f7756
200
I’d Like to Thank…
award_1703f934-cf44-40cc-a96d-3729d0b48262
My kindergarten teacher, my cat, my mom, and you.
200
I’m Deceased
award_b28d9565-4137-433d-bb65-5d4aa82ade4c
Call an ambulance, I’m laughing too hard.
200
Looking
award_4922c1be-3646-4d62-96ea-19a56798df51
I can’t help but look.
200
Lurking
award_59ae34c0-14c8-4b16-a527-e157fac0a6c7
Just seeing what’s going on
200
Plus One
award_f7562045-905d-413e-9ed2-0a16d4bfe349
You officially endorse and add your voice to the crowd.
200
Sidevote
award_cd297f1a-8368-4f5a-acb8-6ec96fc6e8d6
Not an upvote, not a downvote, just an in-the- middle sidevote.
200
Stone Face
award_2c3bb816-f6fc-46e8-aaf7-2b196afffada
You got me stone faced
200
Stonks Falling
award_9ee30a8f-463e-4ef7-9da9-a09f270ec026
Losing value fast.
200
Stonks Rising
award_d125d124-5c03-490d-af3d-d07c462003da
To the MOON.
200
1UP
award_11be92ba-509e-46d3-991b-593239006521
Extra life
250
Are You Serious?
award_ca888c60-cd8c-4875-97f1-b536dc35a9a5
Are you being serious right now?
250
Are You Winning?
award_5641bae4-e690-4832-a498-4bd78da8b2b1
Well, are you?
250
Awesome Answer
award_2adc49e8-d6c9-4923-9293-2bfab1648569
For a winning take and the kind soul who nails a question. Gives %{coin_symbol}100 Coins to both the author and the community.
250
Big Brain Time
award_e71deb9c-a466-4743-9a73-48771c000077
2000 IQ
250
Calculating
award_242c4f2c-6f1c-4387-9b5b-d0249d6ecd36
Something isn’t adding up
250
Confetti
award_1671746c-49e2-4cdd-be4e-ec8892434278
Party time, shower them with sparkly paper
250
Doom
award_e03a0c52-56b5-45df-bd6f-5f2da10cfdc5
A sense of impending doom
250
Duck Dance
award_c3e02835-9444-4a7f-9e7f-206e8bf0ed99
He do be dancing though
250
Endless Coolness
award_aac76dbe-2272-4fad-ac06-c077d2d9049e
Cool to the infinity
250
It’s Cute!
award_cc540de7-dfdb-4a68-9acf-6f9ce6b17d21
You made me UwU.
250
Laser Eyes
award_e1ed6fb9-f23e-4cb4-aad9-70c83e4b1924
250
Mind Blown
award_9583d210-a7d0-4f3c-b0c7-369ad579d3d4
When a thing immediately combusts your brain. Gives %{coin_symbol}100 Coins to both the author and the community.
250
Original
award_d306c865-0d49-4a36-a1ab-a4122a0e3480
When something new and creative wows you. Gives %{coin_symbol}100 Coins to both the author and the community.
250
Pranked!
award_e2250c69-8bd9-4e2f-8fb7-e6630e6c5c8a
Cake direct to face
250
Respect
award_c8503d66-6450-40c5-963f-35ced99bd361
Tip of my hat to you
250
That Smile
award_e11fc833-31fe-4c43-bde8-aead928b4b70
Cute but creepy
250
Timeless Beauty
award_31260000-2f4a-4b40-ad20-f5aa46a577bf
Beauty that’s forever. Gives %{coin_symbol}100 Coins each to the author and the community.
250
Today I Learned
award_a67d649d-5aa5-407e-a98b-32fd9e3a9696
The more you know… Gives %{coin_symbol}100 Coins to both the author and the community.
250
Vibing
award_3f4e6f36-dacc-4919-b170-9d0201cd258f
I’m catching the vibration
250
Wink Wink
award_a8196b8f-1a76-4902-b324-b9473854dade
nudge, nudge
250
Woah Dude
award_d88c5520-18d0-4ef0-9a36-41f8617584b0
Sometimes you’re left just going WOAH…
250
Yas Queen
award_d48aad4b-286f-4a3a-bb41-ec05b3cd87cc
YAAAAAAAAAAASSS.
250
You Dropped This
award_92d8645c-de2c-44ae-8cd7-7b0c6ab25297
King
250
hehehehe
award_435a5692-f508-4b31-8083-ddc576f26ad3
That’s a little funny
250
Blow a Kiss
award_9ef35273-7942-4199-a76a-3d37f3b52a2e
smooch
300
Coin Gift
award_3dd248bc-3438-4c5b-98d4-24421fd6d670
Give the gift of %{coin_symbol}250 Reddit Coins.
300
Crab Rave
award_f7a4fd5e-7cd1-4c11-a1c9-c18d05902e81
[Happy crab noises]
300
GOAT
award_cc299d65-77de-4828-89de-708b088349a0
Historical anomaly - greatest in eternity.
300
Heartbreak
award_dc85c1f3-b5aa-4970-9a5d-40304252f79e
Suffering from a broken heart
300
Rocket Like
award_28e8196b-d4e9-45bc-b612-cd4c7d3ed4b3
When an upvote just isn’t enough, smash the Rocket Like.
300
Table Flip
award_3e000ecb-c1a4-49dc-af14-c8ac2029ca97
ARGH!
300
This
award_68ba1ee3-9baf-4252-be52-b808c1e8bdc4
THIS right here! Join together to give multiple This awards and see the award evolve in its display and shower benefits for the recipient. For every 3 This awards given to a post or comment, the author will get 250 coins.
300
Updoot
award_725b427d-320b-4d02-8fb0-8bb7aa7b78aa
Sometimes you just got to doot.
300
Wait What?
award_a3b7d374-68b4-4c77-8a57-e11fd6f26c06
Hold up, what was that?
300
Spit-take
award_3409a4c0-ba69-43a0-be9f-27bc27c159cc
Shower them with laughs
325
Super Heart Eyes
award_6220ecfe-4552-4949-aa13-fb1fb7db537c
When the love is out of control.
325
Table Slap
award_9f928aff-c9f5-4e7e-aa91-8619dce60f1c
When laughter meets percussion
325
To The Stars
award_2bc47247-b107-44a8-a78c-613da21869ff
Boldly go where we haven’t been in a long, long time.
325
Into the Magic Portal
award_2ff1fdd0-ff73-47e6-a43c-bde6d4de8fbd
Hope to make it to the other side.
350
Out of the Magic Portal
award_7fe72f36-1141-4a39-ba76-0d481889b390
That was fun, but I’m glad to be back
350
Bravo!
award_84276b1e-cc8f-484f-a19c-be6c09adc1a5
An amazing showing.
400
Doot 🎵 Doot
award_5b39e8fd-7a58-4cbe-8ca0-bdedd5ed1f5a
Sometimes you just got to dance with the doots.
400
Bless Up (Pro)
award_43c43a35-15c5-4f73-91ef-fe538426435a
Prayers up for the blessed. Gives %{coin_symbol}100 Coins to both the author and the community.
500
Brighten My Day
award_9591a26e-b2e4-4ef2-bed4-28ff69246691
The clouds part and the sun shines through. Use the Brighten My Day Award to highlight comments that are a ray of sunshine.
500
Eureka!
award_65f78ca2-45d8-4cb6-bf79-a67beadf2e47
Now that is a bright idea. Use the Eureka Award to highlight comments that are brilliant.
500
Heart Eyes
award_a9009ea5-1a36-42ae-aab2-5967563ee054
For love at first sight. Gives %{coin_symbol}100 Coins to both the author and the community.
500
Helpful (Pro)
award_2ae56630-cfe0-424e-b810-4945b9145358
Thank you stranger. Gives %{coin_symbol}100 Coins to both the author and the community.
500
Made Me Smile
award_a7a04d6a-8dd8-41bb-b906-04fa8f144014
When you’re smiling before you know it. Gives %{coin_symbol}100 Coins to both the author and the community.
500
Starry
award_0e957fb0-c8f1-4ba1-a8ef-e1e524b60d7d
Use the Starry Award to highlight comments that deserve to stand out from the crowd.
500
Wholesome (Pro)
award_1f0462ee-18f5-4f33-89cf-f1f79336a452
When you come across a feel-good thing. Gives %{coin_symbol}100 Coins to both the author and the community.
500
Pot o’ Coins
award_35c78e6e-507b-4f1d-b3d8-ed43840909a8
The treasure at the end of the rainbow. Gives the author 800 Coins to do with as they please.
1000
Argentium
award_4ca5a4e6-8873-4ac5-99b9-71b1d5161a91
Latin for distinguished, this award shimmers like silver and is stronger than steel. It’s for those who deserve outsized recognition. Gives 2,500 Reddit Coins and three months of r/lounge access and ad-free browsing.
20000
Ternion All-Powerful
award_2385c499-a1fb-44ec-b9b7-d260f3dc55de
Legendary level, this award is a no holds barred celebration of something that hits you in the heart, mind, and soul. Some might call it unachievanium. Gives 5,000 Reddit Coins and six months of r/lounge access and ad-free browsing.
50000
- block()
Block the user who sent the item.
Note
This method pertains only to objects which were retrieved via the inbox.
Example usage:
comment = reddit.comment("dkk4qjd") comment.block() # or, identically: comment.author.block()
- clear_vote()
Clear the authenticated user’s vote on the object.
Note
Votes must be cast by humans. That is, API clients proxying a human’s action one-for-one are OK, but bots deciding how to vote on content or amplifying a human’s vote are not. See the reddit rules for more details on what constitutes vote manipulation. [Ref]
Example usage:
submission = reddit.submission("5or86n") submission.clear_vote() comment = reddit.comment("dxolpyc") comment.clear_vote()
- collapse()
Mark the item as collapsed.
Note
This method pertains only to objects which were retrieved via the inbox.
Example usage:
inbox = reddit.inbox() # select first inbox item and collapse it message = next(inbox) message.collapse()
See also
- delete()
Delete the object.
Example usage:
comment = reddit.comment("dkk4qjd") comment.delete() submission = reddit.submission("8dmv8z") submission.delete()
- disable_inbox_replies()
Disable inbox replies for the item.
Example usage:
comment = reddit.comment("dkk4qjd") comment.disable_inbox_replies() submission = reddit.submission("8dmv8z") submission.disable_inbox_replies()
See also
- downvote()
Downvote the object.
Note
Votes must be cast by humans. That is, API clients proxying a human’s action one-for-one are OK, but bots deciding how to vote on content or amplifying a human’s vote are not. See the reddit rules for more details on what constitutes vote manipulation. [Ref]
Example usage:
submission = reddit.submission("5or86n") submission.downvote() comment = reddit.comment("dxolpyc") comment.downvote()
See also
- edit(body: str) praw.models.Comment | praw.models.Submission
Replace the body of the object with
body
.- Parameters:
body – The Markdown formatted content for the updated object.
- Returns:
The current instance after updating its attributes.
Example usage:
comment = reddit.comment("dkk4qjd") # construct the text of an edited comment # by appending to the old body: edited_body = comment.body + "Edit: thanks for the gold!" comment.edit(edited_body)
- enable_inbox_replies()
Enable inbox replies for the item.
Example usage:
comment = reddit.comment("dkk4qjd") comment.enable_inbox_replies() submission = reddit.submission("8dmv8z") submission.enable_inbox_replies()
See also
- property fullname: str
Return the object’s fullname.
A fullname is an object’s kind mapping like
t3
followed by an underscore and the object’s base36 ID, e.g.,t1_c5s96e0
.
- mark_read()
Mark a single inbox item as read.
Note
This method pertains only to objects which were retrieved via the inbox.
Example usage:
inbox = reddit.inbox.unread() for message in inbox: # process unread messages ...
See also
To mark the whole inbox as read with a single network request, use
Inbox.mark_all_read()
- mark_unread()
Mark the item as unread.
Note
This method pertains only to objects which were retrieved via the inbox.
Example usage:
inbox = reddit.inbox(limit=10) for message in inbox: # process messages ...
See also
- mod() praw.models.reddit.comment.CommentModeration
Provide an instance of
CommentModeration
.Example usage:
comment = reddit.comment("dkk4qjd") comment.mod.approve()
- parent() Comment | praw.models.Submission
Return the parent of the comment.
The returned parent will be an instance of either
Comment
, orSubmission
.If this comment was obtained through a
Submission
, then its entire ancestry should be immediately available, requiring no extra network requests. However, if this comment was obtained through other means, e.g.,reddit.comment("COMMENT_ID")
, orreddit.inbox.comment_replies
, then the returned parent may be a lazy instance of eitherComment
, orSubmission
.Lazy comment example:
comment = reddit.comment("cklhv0f") parent = comment.parent() # 'replies' is empty until the comment is refreshed print(parent.replies) # Output: [] parent.refresh() print(parent.replies) # Output is at least: [Comment(id="cklhv0f")]
Warning
Successive calls to
parent()
may result in a network request per call when the comment is not obtained through aSubmission
. See below for an example of how to minimize requests.If you have a deeply nested comment and wish to most efficiently discover its top-most
Comment
ancestor you can chain successive calls toparent()
with calls torefresh()
at every 9 levels. For example:comment = reddit.comment("dkk4qjd") ancestor = comment refresh_counter = 0 while not ancestor.is_root: ancestor = ancestor.parent() if refresh_counter % 9 == 0: ancestor.refresh() refresh_counter += 1 print(f"Top-most Ancestor: {ancestor}")
The above code should result in 5 network requests to Reddit. Without the calls to
refresh()
it would make at least 31 network requests.
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit) Any
Return an instance of
cls
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.
- refresh()
Refresh the comment’s attributes.
If using
Reddit.comment()
this method must be called in order to obtain the comment’s replies.Example usage:
comment = reddit.comment("dkk4qjd") comment.refresh()
- property replies: CommentForest
Provide an instance of
CommentForest
.This property may return an empty list if the comment has not been refreshed with
refresh()
Sort order and reply limit can be set with the
reply_sort
andreply_limit
attributes before replies are fetched, including any call torefresh()
:comment.reply_sort = "new" comment.refresh() replies = comment.replies
Note
The appropriate values for
reply_sort
include"confidence"
,"controversial"
,"new"
,"old"
,"q&a"
, and"top"
.
- reply(body: str) praw.models.Comment | praw.models.Message | None
Reply to the object.
- Parameters:
body – The Markdown formatted content for a comment.
- Returns:
A
Comment
orMessage
object for the newly created comment or message orNone
if Reddit doesn’t provide one.- Raises:
prawcore.exceptions.Forbidden
when attempting to reply to some items, such as locked submissions/comments or non-replyable messages.
A
None
value can be returned if the target is a comment or submission in a quarantined subreddit and the authenticated user has not opt-ed into viewing the content. When this happens the comment will be successfully created on Reddit and can be retried by drawing the comment from the user’s comment history.Example usage:
submission = reddit.submission("5or86n") submission.reply("reply") comment = reddit.comment("dxolpyc") comment.reply("reply")
- report(reason: str)
Report this object to the moderators of its subreddit.
- Parameters:
reason – The reason for reporting.
- Raises:
RedditAPIException
ifreason
is longer than 100 characters.
Example usage:
submission = reddit.submission("5or86n") submission.report("report reason") comment = reddit.comment("dxolpyc") comment.report("report reason")
- save(*, category: str | None = None)
Save the object.
- Parameters:
category – The category to save to. If the authenticated user does not have Reddit Premium this value is ignored by Reddit (default:
None
).
Example usage:
submission = reddit.submission("5or86n") submission.save(category="view later") comment = reddit.comment("dxolpyc") comment.save()
See also
- property submission: praw.models.Submission
Return the
Submission
object this comment belongs to.
- unblock_subreddit()
Unblock a subreddit.
Note
This method pertains only to objects which were retrieved via the inbox.
For example, to unblock all blocked subreddits that you can find by going through your inbox:
from praw.models import SubredditMessage subs = set() for item in reddit.inbox.messages(limit=None): if isinstance(item, SubredditMessage): if ( item.subject == "[message from blocked subreddit]" and str(item.subreddit) not in subs ): item.unblock_subreddit() subs.add(str(item.subreddit))
- uncollapse()
Mark the item as uncollapsed.
Note
This method pertains only to objects which were retrieved via the inbox.
Example usage:
inbox = reddit.inbox() # select first inbox item and uncollapse it message = next(inbox) message.uncollapse()
See also
- unsave()
Unsave the object.
Example usage:
submission = reddit.submission("5or86n") submission.unsave() comment = reddit.comment("dxolpyc") comment.unsave()
See also
- upvote()
Upvote the object.
Note
Votes must be cast by humans. That is, API clients proxying a human’s action one-for-one are OK, but bots deciding how to vote on content or amplifying a human’s vote are not. See the reddit rules for more details on what constitutes vote manipulation. [Ref]
Example usage:
submission = reddit.submission("5or86n") submission.upvote() comment = reddit.comment("dxolpyc") comment.upvote()
See also
Draft
- class praw.models.Draft(reddit: praw.Reddit, id: str | None = None, _data: Dict[str, Any] = None)
A class that represents a Reddit submission draft.
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
link_flair_template_id
The link flair’s ID.
link_flair_text
The link flair’s text content, or
None
if not flaired.modified
Time the submission draft was modified, represented in Unix Time.
original_content
Whether the submission draft will be set as original content.
selftext
The submission draft’s selftext.
None
if a link submission draft.spoiler
Whether the submission will be marked as a spoiler.
subreddit
Provides an instance of
Subreddit
orUserSubreddit
(if set).title
The title of the submission draft.
url
The URL the submission draft links to.
- __init__(reddit: praw.Reddit, id: str | None = None, _data: Dict[str, Any] = None)
Initialize a
Draft
instance.
- delete()
Delete the
Draft
.Example usage:
draft = reddit.drafts("124862bc-e1e9-11eb-aa4f-e68667a77cbb") draft.delete()
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit) Any
Return an instance of
cls
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.
- submit(*, flair_id: str | None = None, flair_text: str | None = None, nsfw: bool | None = None, selftext: str | None = None, spoiler: bool | None = None, subreddit: str | praw.models.Subreddit | praw.models.UserSubreddit | None = None, title: str | None = None, url: str | None = None, **submit_kwargs) praw.models.Submission
Submit a draft.
- Parameters:
flair_id – The flair template to select (default:
None
).flair_text – If the template’s
flair_text_editable
value isTrue
, this value will set a custom text (default:None
).flair_id
is required whenflair_text
is provided.nsfw – Whether or not the submission should be marked NSFW (default:
None
).selftext – The Markdown formatted content for a
text
submission. Use an empty string,""
, to make a title-only submission (default:None
).spoiler – Whether or not the submission should be marked as a spoiler (default:
None
).subreddit – The subreddit to submit the draft to. This accepts a subreddit display name,
Subreddit
object, orUserSubreddit
object.title – The title of the submission (default:
None
).url – The URL for a
link
submission (default:None
).
- Returns:
A
Submission
object for the newly created submission.
Note
Parameters set here will override their respective
Draft
attributes.Additional keyword arguments are passed to the
Subreddit.submit()
method.For example, to submit a draft as is:
draft = reddit.drafts("5f87d55c-e4fb-11eb-8965-6aeb41b0880e") submission = draft.submit()
For example, to submit a draft but use a different title than what is set:
draft = reddit.drafts("5f87d55c-e4fb-11eb-8965-6aeb41b0880e") submission = draft.submit(title="New Title")
See also
submit()
to submit url posts and selftextssubmit_gallery()
. to submit more than one image in the same postsubmit_image()
to submit imagessubmit_poll()
to submit pollssubmit_video()
to submit videos and videogifs
- update(*, flair_id: str | None = None, flair_text: str | None = None, is_public_link: bool | None = None, nsfw: bool | None = None, original_content: bool | None = None, selftext: str | None = None, send_replies: bool | None = None, spoiler: bool | None = None, subreddit: str | praw.models.Subreddit | praw.models.UserSubreddit | None = None, title: str | None = None, url: str | None = None, **draft_kwargs)
Update the
Draft
.Note
Only provided values will be updated.
- Parameters:
flair_id – The flair template to select.
flair_text – If the template’s
flair_text_editable
value isTrue
, this value will set a custom text.flair_id
is required whenflair_text
is provided.is_public_link – Whether to enable public viewing of the draft before it is submitted.
nsfw – Whether the draft should be marked NSFW.
original_content – Whether the submission should be marked as original content.
selftext – The Markdown formatted content for a text submission draft. Use
None
to make a title-only submission draft.selftext
can not be provided ifurl
is provided.send_replies – When
True
, messages will be sent to the submission author when comments are made to the submission.spoiler – Whether the submission should be marked as a spoiler.
subreddit – The subreddit to create the draft for. This accepts a subreddit display name,
Subreddit
object, orUserSubreddit
object.title – The title of the draft.
url – The URL for a
link
submission draft.url
can not be provided ifselftext
is provided.
Additional keyword arguments can be provided to handle new parameters as Reddit introduces them.
For example, to update the title of a draft do:
draft = reddit.drafts("5f87d55c-e4fb-11eb-8965-6aeb41b0880e") draft.update(title="New title")
LiveThread
- class praw.models.LiveThread(reddit: praw.Reddit, id: str | None = None, _data: Dict[str, Any] | None = None)
An individual
LiveThread
object.Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
created_utc
The creation time of the live thread, in Unix Time.
description
Description of the live thread, as Markdown.
description_html
Description of the live thread, as HTML.
id
The ID of the live thread.
nsfw
A
bool
representing whether or not the live thread is marked as NSFW.- __getitem__(update_id: str) praw.models.LiveUpdate
Return a lazy
LiveUpdate
instance.- Parameters:
update_id – A live update ID, e.g.,
"7827987a-c998-11e4-a0b9-22000b6a88d2"
.
Usage:
thread = reddit.live("ukaeu1ik4sw5") update = thread["7827987a-c998-11e4-a0b9-22000b6a88d2"] update.thread # LiveThread(id="ukaeu1ik4sw5") update.id # "7827987a-c998-11e4-a0b9-22000b6a88d2" update.author # "umbrae"
- __init__(reddit: praw.Reddit, id: str | None = None, _data: Dict[str, Any] | None = None)
Initialize a
LiveThread
instance.- Parameters:
reddit – An instance of
Reddit
.id – A live thread ID, e.g.,
"ukaeu1ik4sw5"
- contrib() praw.models.reddit.live.LiveThreadContribution
Provide an instance of
LiveThreadContribution
.Usage:
thread = reddit.live("ukaeu1ik4sw5") thread.contrib.add("### update")
- contributor() praw.models.reddit.live.LiveContributorRelationship
Provide an instance of
LiveContributorRelationship
.You can call the instance to get a list of contributors which is represented as
RedditorList
instance consists ofRedditor
instances. ThoseRedditor
instances havepermissions
attributes as contributors:thread = reddit.live("ukaeu1ik4sw5") for contributor in thread.contributor(): # prints `Redditor(name="Acidtwist") ["all"]` print(contributor, contributor.permissions)
- discussions(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Submission]
Get submissions linking to the thread.
- Parameters:
generator_kwargs – keyword arguments passed to
ListingGenerator
constructor.- Returns:
A
ListingGenerator
object which yieldsSubmission
objects.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.Usage:
thread = reddit.live("ukaeu1ik4sw5") for submission in thread.discussions(limit=None): print(submission.title)
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit) Any
Return an instance of
cls
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.
- report(type: str)
Report the thread violating the Reddit rules.
- Parameters:
type – One of
"spam"
,"vote-manipulation"
,"personal- information"
,"sexualizing-minors"
, or"site-breaking"
.
Usage:
thread = reddit.live("xyu8kmjvfrww") thread.report("spam")
- stream() praw.models.reddit.live.LiveThreadStream
Provide an instance of
LiveThreadStream
.Streams are used to indefinitely retrieve new updates made to a live thread, like:
for live_update in reddit.live("ta535s1hq2je").stream.updates(): print(live_update.body)
Updates are yielded oldest first as
LiveUpdate
. Up to 100 historical updates will initially be returned. To only retrieve new updates starting from when the stream is created, passskip_existing=True
:live_thread = reddit.live("ta535s1hq2je") for live_update in live_thread.stream.updates(skip_existing=True): print(live_update.author)
- updates(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.LiveUpdate]
Return a
ListingGenerator
yieldsLiveUpdate
s.- Parameters:
generator_kwargs – keyword arguments passed to
ListingGenerator
constructor.- Returns:
A
ListingGenerator
object which yieldsLiveUpdate
objects.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.Usage:
thread = reddit.live("ukaeu1ik4sw5") after = "LiveUpdate_fefb3dae-7534-11e6-b259-0ef8c7233633" for submission in thread.updates(limit=5, params={"after": after}): print(submission.body)
LiveUpdate
- class praw.models.LiveUpdate(reddit: praw.Reddit, thread_id: str | None = None, update_id: str | None = None, _data: Dict[str, Any] | None = None)
An individual
LiveUpdate
object.Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
author
The
Redditor
who made the update.body
Body of the update, as Markdown.
body_html
Body of the update, as HTML.
created_utc
The time the update was created, as Unix Time.
stricken
A
bool
representing whether or not the update was stricken (seestrike()
).- __init__(reddit: praw.Reddit, thread_id: str | None = None, update_id: str | None = None, _data: Dict[str, Any] | None = None)
Initialize a
LiveUpdate
instance.Either
thread_id
andupdate_id
, or_data
must be provided.- Parameters:
reddit – An instance of
Reddit
.thread_id – A live thread ID, e.g.,
"ukaeu1ik4sw5"
.update_id – A live update ID, e.g.,
"7827987a-c998-11e4-a0b9-22000b6a88d2"
.
Usage:
update = LiveUpdate(reddit, "ukaeu1ik4sw5", "7827987a-c998-11e4-a0b9-22000b6a88d2") update.thread # LiveThread(id="ukaeu1ik4sw5") update.id # "7827987a-c998-11e4-a0b9-22000b6a88d2" update.author # "umbrae"
- contrib() praw.models.reddit.live.LiveUpdateContribution
Provide an instance of
LiveUpdateContribution
.Usage:
thread = reddit.live("ukaeu1ik4sw5") update = thread["7827987a-c998-11e4-a0b9-22000b6a88d2"] update.contrib # LiveUpdateContribution instance
- property fullname: str
Return the object’s fullname.
A fullname is an object’s kind mapping like
t3
followed by an underscore and the object’s base36 ID, e.g.,t1_c5s96e0
.
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit) Any
Return an instance of
cls
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.
- property thread: LiveThread
Return
LiveThread
object the update object belongs to.
Message
- class praw.models.Message(reddit: praw.Reddit, _data: Dict[str, Any])
A class for private messages.
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
author
Provides an instance of
Redditor
.body
The body of the message, as Markdown.
body_html
The body of the message, as HTML.
created_utc
Time the message was created, represented in Unix Time.
dest
Provides an instance of
Redditor
. The recipient of the message.id
The ID of the message.
name
The full ID of the message, prefixed with
t4_
.subject
The subject of the message.
was_comment
Whether or not the message was a comment reply.
- block()
Block the user who sent the item.
Note
This method pertains only to objects which were retrieved via the inbox.
Example usage:
comment = reddit.comment("dkk4qjd") comment.block() # or, identically: comment.author.block()
- collapse()
Mark the item as collapsed.
Note
This method pertains only to objects which were retrieved via the inbox.
Example usage:
inbox = reddit.inbox() # select first inbox item and collapse it message = next(inbox) message.collapse()
See also
- delete()
Delete the message.
Note
Reddit does not return an indication of whether or not the message was successfully deleted.
For example, to delete the most recent message in your inbox:
next(reddit.inbox.all()).delete()
- property fullname: str
Return the object’s fullname.
A fullname is an object’s kind mapping like
t3
followed by an underscore and the object’s base36 ID, e.g.,t1_c5s96e0
.
- mark_read()
Mark a single inbox item as read.
Note
This method pertains only to objects which were retrieved via the inbox.
Example usage:
inbox = reddit.inbox.unread() for message in inbox: # process unread messages ...
See also
To mark the whole inbox as read with a single network request, use
Inbox.mark_all_read()
- mark_unread()
Mark the item as unread.
Note
This method pertains only to objects which were retrieved via the inbox.
Example usage:
inbox = reddit.inbox(limit=10) for message in inbox: # process messages ...
See also
- property parent: praw.models.Message | None
Return the parent of the message if it exists.
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit)
Return an instance of
Message
orSubredditMessage
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.
- reply(body: str) praw.models.Comment | praw.models.Message | None
Reply to the object.
- Parameters:
body – The Markdown formatted content for a comment.
- Returns:
A
Comment
orMessage
object for the newly created comment or message orNone
if Reddit doesn’t provide one.- Raises:
prawcore.exceptions.Forbidden
when attempting to reply to some items, such as locked submissions/comments or non-replyable messages.
A
None
value can be returned if the target is a comment or submission in a quarantined subreddit and the authenticated user has not opt-ed into viewing the content. When this happens the comment will be successfully created on Reddit and can be retried by drawing the comment from the user’s comment history.Example usage:
submission = reddit.submission("5or86n") submission.reply("reply") comment = reddit.comment("dxolpyc") comment.reply("reply")
- unblock_subreddit()
Unblock a subreddit.
Note
This method pertains only to objects which were retrieved via the inbox.
For example, to unblock all blocked subreddits that you can find by going through your inbox:
from praw.models import SubredditMessage subs = set() for item in reddit.inbox.messages(limit=None): if isinstance(item, SubredditMessage): if ( item.subject == "[message from blocked subreddit]" and str(item.subreddit) not in subs ): item.unblock_subreddit() subs.add(str(item.subreddit))
- uncollapse()
Mark the item as uncollapsed.
Note
This method pertains only to objects which were retrieved via the inbox.
Example usage:
inbox = reddit.inbox() # select first inbox item and uncollapse it message = next(inbox) message.uncollapse()
See also
ModmailConversation
- class praw.models.reddit.modmail.ModmailConversation(reddit: praw.Reddit, id: str | None = None, mark_read: bool = False, _data: Dict[str, Any] | None = None)
A class for modmail conversations.
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
authors
Provides an ordered list of
Redditor
instances. The authors of each message in the modmail conversation.id
The ID of the
ModmailConversation
.is_highlighted
Whether or not the
ModmailConversation
is highlighted.is_internal
Whether or not the
ModmailConversation
is a private mod conversation.last_mod_update
Time of the last mod message reply, represented in the ISO 8601 standard with timezone.
last_updated
Time of the last message reply, represented in the ISO 8601 standard with timezone.
last_user_update
Time of the last user message reply, represented in the ISO 8601 standard with timezone.
num_messages
The number of messages in the
ModmailConversation
.obj_ids
Provides a list of dictionaries representing mod actions on the
ModmailConversation
. Each dict contains attributes of"key"
and"id"
. The key can be either""messages"
or"ModAction"
."ModAction"
represents archiving/highlighting etc.owner
Provides an instance of
Subreddit
. The subreddit that theModmailConversation
belongs to.participant
Provides an instance of
Redditor
. The participating user in theModmailConversation
.subject
The subject of the
ModmailConversation
.- __init__(reddit: praw.Reddit, id: str | None = None, mark_read: bool = False, _data: Dict[str, Any] | None = None)
Initialize a
ModmailConversation
instance.- Parameters:
mark_read – If
True
, conversation is marked as read (default:False
).
- archive()
Archive the conversation.
For example:
reddit.subreddit("test").modmail("2gmz").archive()
- highlight()
Highlight the conversation.
For example:
reddit.subreddit("test").modmail("2gmz").highlight()
- mute(*, num_days=3)
Mute the non-mod user associated with the conversation.
- Parameters:
num_days – Duration of mute in days. Valid options are
3
,7
, or28
(default:3
).
For example:
reddit.subreddit("test").modmail("2gmz").mute()
To mute for 7 days:
reddit.subreddit("test").modmail("2gmz").mute(num_days=7)
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit, convert_objects: bool = True)
Return an instance of
ModmailConversation
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.convert_objects – If
True
, convert message and mod action data into objects (default:True
).
- read(*, other_conversations: List[ModmailConversation] | None = None)
Mark the conversation(s) as read.
- Parameters:
other_conversations – A list of other conversations to mark (default:
None
).
For example, to mark the conversation as read along with other recent conversations from the same user:
subreddit = reddit.subreddit("test") conversation = subreddit.modmail.conversation("2gmz") conversation.read(other_conversations=conversation.user.recent_convos)
- reply(*, author_hidden: bool = False, body: str, internal: bool = False) ModmailMessage
Reply to the conversation.
- Parameters:
author_hidden – When
True
, author is hidden from non-moderators (default:False
).body – The Markdown formatted content for a message.
internal – When
True
, message is a private moderator note, hidden from non-moderators (default:False
).
- Returns:
A
ModmailMessage
object for the newly created message.
For example, to reply to the non-mod user while hiding your username:
conversation = reddit.subreddit("test").modmail("2gmz") conversation.reply(body="Message body", author_hidden=True)
To create a private moderator note on the conversation:
conversation.reply(body="Message body", internal=True)
- unarchive()
Unarchive the conversation.
For example:
reddit.subreddit("test").modmail("2gmz").unarchive()
- unhighlight()
Un-highlight the conversation.
For example:
reddit.subreddit("test").modmail("2gmz").unhighlight()
- unmute()
Unmute the non-mod user associated with the conversation.
For example:
reddit.subreddit("test").modmail("2gmz").unmute()
- unread(*, other_conversations: List[ModmailConversation] | None = None)
Mark the conversation(s) as unread.
- Parameters:
other_conversations – A list of other conversations to mark (default:
None
).
For example, to mark the conversation as unread along with other recent conversations from the same user:
subreddit = reddit.subreddit("test") conversation = subreddit.modmail.conversation("2gmz") conversation.unread(other_conversations=conversation.user.recent_convos)
MoreComments
- class praw.models.MoreComments(reddit: praw.Reddit, _data: Dict[str, Any])
A class indicating there are more comments.
- __init__(reddit: praw.Reddit, _data: Dict[str, Any])
Initialize a
MoreComments
instance.
- comments(*, update: bool = True) List[praw.models.Comment]
Fetch and return the comments for a single
MoreComments
object.
Multireddit
- class praw.models.Multireddit(reddit: praw.Reddit, _data: Dict[str, Any])
A class for users’ multireddits.
This is referred to as a “Custom Feed” on the Reddit UI.
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
can_edit
A
bool
representing whether or not the authenticated user may edit the multireddit.copied_from
The multireddit that the multireddit was copied from, if it exists, otherwise
None
.created_utc
When the multireddit was created, in Unix Time.
description_html
The description of the multireddit, as HTML.
description_md
The description of the multireddit, as Markdown.
display_name
The display name of the multireddit.
name
The name of the multireddit.
over_18
A
bool
representing whether or not the multireddit is restricted for users over 18.subreddits
A list of
Subreddit
s that make up the multireddit.visibility
The visibility of the multireddit, either
"private"
,"public"
, or"hidden"
.- __init__(reddit: praw.Reddit, _data: Dict[str, Any])
Initialize a
Multireddit
instance.
- add(subreddit: praw.models.Subreddit)
Add a subreddit to this multireddit.
- Parameters:
subreddit – The subreddit to add to this multi.
For example, to add r/test to multireddit
bboe/test
:subreddit = reddit.subreddit("test") reddit.multireddit(redditor="bboe", name="test").add(subreddit)
- comments() CommentHelper
Provide an instance of
CommentHelper
.For example, to output the author of the 25 most recent comments of r/test execute:
for comment in reddit.subreddit("test").comments(limit=25): print(comment.author)
- controversial(*, time_filter: str = 'all', **generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for controversial items.- Parameters:
time_filter – Can be one of:
"all"
,"day"
,"hour"
,"month"
,"week"
, or"year"
(default:"all"
).- Raises:
ValueError
iftime_filter
is invalid.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").controversial(time_filter="week") reddit.multireddit(redditor="samuraisam", name="programming").controversial( time_filter="day" ) reddit.redditor("spez").controversial(time_filter="month") reddit.redditor("spez").comments.controversial(time_filter="year") reddit.redditor("spez").submissions.controversial(time_filter="all") reddit.subreddit("all").controversial(time_filter="hour")
- copy(*, display_name: str | None = None) praw.models.Multireddit
Copy this multireddit and return the new multireddit.
- Parameters:
display_name – The display name for the copied multireddit. Reddit will generate the
name
field from this display name. When not provided the copy will use the same display name and name as this multireddit.
To copy the multireddit
bboe/test
with a name of"testing"
:reddit.multireddit(redditor="bboe", name="test").copy(display_name="testing")
- delete()
Delete this multireddit.
For example, to delete multireddit
bboe/test
:reddit.multireddit(redditor="bboe", name="test").delete()
- gilded(**generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for gilded items.Additional keyword arguments are passed in the initialization of
ListingGenerator
.For example, to get gilded items in r/test:
for item in reddit.subreddit("test").gilded(): print(item.id)
- hot(**generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for hot items.Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").hot() reddit.multireddit(redditor="samuraisam", name="programming").hot() reddit.redditor("spez").hot() reddit.redditor("spez").comments.hot() reddit.redditor("spez").submissions.hot() reddit.subreddit("all").hot()
- new(**generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for new items.Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").new() reddit.multireddit(redditor="samuraisam", name="programming").new() reddit.redditor("spez").new() reddit.redditor("spez").comments.new() reddit.redditor("spez").submissions.new() reddit.subreddit("all").new()
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit) Any
Return an instance of
cls
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.
- random_rising(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Submission]
Return a
ListingGenerator
for random rising submissions.Additional keyword arguments are passed in the initialization of
ListingGenerator
.For example, to get random rising submissions for r/test:
for submission in reddit.subreddit("test").random_rising(): print(submission.title)
- remove(subreddit: praw.models.Subreddit)
Remove a subreddit from this multireddit.
- Parameters:
subreddit – The subreddit to remove from this multi.
For example, to remove r/test from multireddit
bboe/test
:subreddit = reddit.subreddit("test") reddit.multireddit(redditor="bboe", name="test").remove(subreddit)
- rising(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Submission]
Return a
ListingGenerator
for rising submissions.Additional keyword arguments are passed in the initialization of
ListingGenerator
.For example, to get rising submissions for r/test:
for submission in reddit.subreddit("test").rising(): print(submission.title)
- static sluggify(title: str)
Return a slug version of the title.
- Parameters:
title – The title to make a slug of.
Adapted from Reddit’s utils.py.
- stream() SubredditStream
Provide an instance of
SubredditStream
.Streams can be used to indefinitely retrieve new comments made to a multireddit, like:
for comment in reddit.multireddit(redditor="spez", name="fun").stream.comments(): print(comment)
Additionally, new submissions can be retrieved via the stream. In the following example all new submissions to the multireddit are fetched:
for submission in reddit.multireddit( redditor="bboe", name="games" ).stream.submissions(): print(submission)
- top(*, time_filter: str = 'all', **generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for top items.- Parameters:
time_filter – Can be one of:
"all"
,"day"
,"hour"
,"month"
,"week"
, or"year"
(default:"all"
).- Raises:
ValueError
iftime_filter
is invalid.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").top(time_filter="week") reddit.multireddit(redditor="samuraisam", name="programming").top(time_filter="day") reddit.redditor("spez").top(time_filter="month") reddit.redditor("spez").comments.top(time_filter="year") reddit.redditor("spez").submissions.top(time_filter="all") reddit.subreddit("all").top(time_filter="hour")
- update(**updated_settings: str | List[str | praw.models.Subreddit | Dict[str, str]])
Update this multireddit.
Keyword arguments are passed for settings that should be updated. They can any of:
- Parameters:
display_name – The display name for this multireddit. Must be no longer than 50 characters.
subreddits – Subreddits for this multireddit.
description_md – Description for this multireddit, formatted in Markdown.
icon_name – Can be one of:
"art and design"
,"ask"
,"books"
,"business"
,"cars"
,"comics"
,"cute animals"
,"diy"
,"entertainment"
,"food and drink"
,"funny"
,"games"
,"grooming"
,"health"
,"life advice"
,"military"
,"models pinup"
,"music"
,"news"
,"philosophy"
,"pictures and gifs"
,"science"
,"shopping"
,"sports"
,"style"
,"tech"
,"travel"
,"unusual stories"
,"video"
, orNone
.key_color – RGB hex color code of the form
"#FFFFFF"
.visibility – Can be one of:
"hidden"
,"private"
, or"public"
.weighting_scheme – Can be one of:
"classic"
or"fresh"
.
For example, to rename multireddit
"bboe/test"
to"bboe/testing"
:reddit.multireddit(redditor="bboe", name="test").update(display_name="testing")
Redditor
- class praw.models.Redditor(reddit: praw.Reddit, name: str | None = None, fullname: str | None = None, _data: Dict[str, Any] | None = None)
A class representing the users of Reddit.
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Note
Shadowbanned accounts are treated the same as non-existent accounts, meaning that they will not have any attributes.
Note
Suspended/banned accounts will only return the
name
andis_suspended
attributes.Attribute
Description
comment_karma
The comment karma for the
Redditor
.comments
Provide an instance of
SubListing
for comment access.submissions
Provide an instance of
SubListing
for submission access.created_utc
Time the account was created, represented in Unix Time.
has_verified_email
Whether or not the
Redditor
has verified their email.icon_img
The url of the Redditors’ avatar.
id
The ID of the
Redditor
.is_employee
Whether or not the
Redditor
is a Reddit employee.is_friend
Whether or not the
Redditor
is friends with the authenticated user.is_mod
Whether or not the
Redditor
mods any subreddits.is_gold
Whether or not the
Redditor
has active Reddit Premium status.is_suspended
Whether or not the
Redditor
is currently suspended.link_karma
The link karma for the
Redditor
.name
The Redditor’s username.
subreddit
If the
Redditor
has created a user-subreddit, provides a dictionary of additional attributes. See below.subreddit["banner_img"]
The URL of the user-subreddit banner.
subreddit["name"]
The fullname of the user-subreddit.
subreddit["over_18"]
Whether or not the user-subreddit is NSFW.
subreddit["public_description"]
The public description of the user-subreddit.
subreddit["subscribers"]
The number of users subscribed to the user-subreddit.
subreddit["title"]
The title of the user-subreddit.
- __init__(reddit: praw.Reddit, name: str | None = None, fullname: str | None = None, _data: Dict[str, Any] | None = None)
Initialize a
Redditor
instance.- Parameters:
reddit – An instance of
Reddit
.name – The name of the redditor.
fullname – The fullname of the redditor, starting with
t2_
.
Exactly one of
name
,fullname
or_data
must be provided.
- block()
Block the
Redditor
.For example, to block
Redditor
u/spez:reddit.redditor("spez").block()
Note
Blocking a trusted user will remove that user from your trusted list.
See also
- comments() SubListing
Provide an instance of
SubListing
for comment access.For example, to output the first line of all new comments by u/spez try:
for comment in reddit.redditor("spez").comments.new(limit=None): print(comment.body.split("\\n", 1)[0][:79])
- controversial(*, time_filter: str = 'all', **generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for controversial items.- Parameters:
time_filter – Can be one of:
"all"
,"day"
,"hour"
,"month"
,"week"
, or"year"
(default:"all"
).- Raises:
ValueError
iftime_filter
is invalid.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").controversial(time_filter="week") reddit.multireddit(redditor="samuraisam", name="programming").controversial( time_filter="day" ) reddit.redditor("spez").controversial(time_filter="month") reddit.redditor("spez").comments.controversial(time_filter="year") reddit.redditor("spez").submissions.controversial(time_filter="all") reddit.subreddit("all").controversial(time_filter="hour")
- distrust()
Remove the
Redditor
from your whitelist of trusted users.For example, to remove
Redditor
u/spez from your whitelist:reddit.redditor("spez").distrust()
See also
- downvoted(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Comment | praw.models.Submission]
Return a
ListingGenerator
for items the user has downvoted.- Returns:
A
ListingGenerator
object which yieldsComment
orSubmission
objects the user has downvoted.- Raises:
prawcore.Forbidden
if the user is not authorized to access the list.Note
Since this function returns a
ListingGenerator
the exception may not occur until sometime after this function has returned.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.For example, to get all downvoted items of the authenticated user:
for item in reddit.user.me().downvoted(): print(item.id)
- friend(*, note: str = None)
Friend the
Redditor
.- Parameters:
note – A note to save along with the relationship. Requires Reddit Premium (default:
None
).
Calling this method subsequent times will update the note.
For example, to friend u/spez:
reddit.redditor("spez").friend()
To add a note to the friendship (requires Reddit Premium):
reddit.redditor("spez").friend(note="My favorite admin")
- friend_info() praw.models.Redditor
Return a
Redditor
instance with specific friend-related attributes.- Returns:
A
Redditor
instance with fieldsdate
,id
, and possiblynote
if the authenticated user has Reddit Premium.
For example, to get the friendship information of
Redditor
u/spez:info = reddit.redditor("spez").friend_info friend_data = info.date
- property fullname: str
Return the object’s fullname.
A fullname is an object’s kind mapping like
t3
followed by an underscore and the object’s base36 ID, e.g.,t1_c5s96e0
.
- gild(*, months: int = 1)
Gild the
Redditor
.- Parameters:
months – Specifies the number of months to gild up to 36 (default:
1
).
For example, to gild
Redditor
u/spez for 1 month:reddit.redditor("spez").gild(months=1)
- gilded(**generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for gilded items.Additional keyword arguments are passed in the initialization of
ListingGenerator
.For example, to get gilded items in r/test:
for item in reddit.subreddit("test").gilded(): print(item.id)
- gildings(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Comment | praw.models.Submission]
Return a
ListingGenerator
for items the user has gilded.- Returns:
A
ListingGenerator
object which yieldsComment
orSubmission
objects the user has gilded.- Raises:
prawcore.Forbidden
if the user is not authorized to access the list.Note
Since this function returns a
ListingGenerator
the exception may not occur until sometime after this function has returned.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.For example, to get all gilded items of the authenticated user:
for item in reddit.user.me().gildings(): print(item.id)
Return a
ListingGenerator
for items the user has hidden.- Returns:
A
ListingGenerator
object which yieldsComment
orSubmission
objects the user has hid.- Raises:
prawcore.Forbidden
if the user is not authorized to access the list.Note
Since this function returns a
ListingGenerator
the exception may not occur until sometime after this function has returned.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.For example, to get all hidden items of the authenticated user:
for item in reddit.user.me().hidden(): print(item.id)
- hot(**generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for hot items.Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").hot() reddit.multireddit(redditor="samuraisam", name="programming").hot() reddit.redditor("spez").hot() reddit.redditor("spez").comments.hot() reddit.redditor("spez").submissions.hot() reddit.subreddit("all").hot()
- message(*, from_subreddit: praw.models.Subreddit | str | None = None, message: str, subject: str)
Send a message to a
Redditor
or aSubreddit
’s moderators (modmail).- Parameters:
from_subreddit –
A
Subreddit
instance or string to send the message from. When provided, messages are sent from the subreddit rather than from the authenticated user.Note
The authenticated user must be a moderator of the subreddit and have the
mail
moderator permission.message – The message content.
subject – The subject of the message.
For example, to send a private message to u/spez, try:
reddit.redditor("spez").message(subject="TEST", message="test message from PRAW")
To send a message to u/spez from the moderators of r/test try:
reddit.redditor("spez").message( subject="TEST", message="test message from r/test", from_subreddit="test" )
To send a message to the moderators of r/test, try:
reddit.subreddit("test").message(subject="TEST", message="test PM from PRAW")
- moderated() List[praw.models.Subreddit]
Return a list of the redditor’s moderated subreddits.
- Returns:
A list of
Subreddit
objects. Return[]
if the redditor has no moderated subreddits.- Raises:
prawcore.ServerError
in certain circumstances. See the note below.
Note
The redditor’s own user profile subreddit will not be returned, but other user profile subreddits they moderate will be returned.
Usage:
for subreddit in reddit.redditor("spez").moderated(): print(subreddit.display_name) print(subreddit.title)
Note
A
prawcore.ServerError
exception may be raised if the redditor moderates a large number of subreddits. If that happens, try switching to read-only mode. For example,reddit.read_only = True for subreddit in reddit.redditor("reddit").moderated(): print(str(subreddit))
It is possible that requests made in read-only mode will also raise a
prawcore.ServerError
exception.When used in read-only mode, this method does not retrieve information about subreddits that require certain special permissions to access, e.g., private subreddits and premium-only subreddits.
See also
- multireddits() List[praw.models.Multireddit]
Return a list of the redditor’s public multireddits.
For example, to to get
Redditor
u/spez’s multireddits:multireddits = reddit.redditor("spez").multireddits()
- new(**generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for new items.Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").new() reddit.multireddit(redditor="samuraisam", name="programming").new() reddit.redditor("spez").new() reddit.redditor("spez").comments.new() reddit.redditor("spez").submissions.new() reddit.subreddit("all").new()
- notes() praw.models.RedditorModNotes
Provide an instance of
RedditorModNotes
.This provides an interface for managing moderator notes for a redditor.
Note
The authenticated user must be a moderator of the provided subreddit(s).
For example, all the notes for u/spez in r/test can be iterated through like so:
redditor = reddit.redditor("spez") for note in redditor.notes.subreddits("test"): print(f"{note.label}: {note.note}")
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit) Any
Return an instance of
cls
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.
- saved(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Comment | praw.models.Submission]
Return a
ListingGenerator
for items the user has saved.- Returns:
A
ListingGenerator
object which yieldsComment
orSubmission
objects the user has saved.- Raises:
prawcore.Forbidden
if the user is not authorized to access the list.Note
Since this function returns a
ListingGenerator
the exception may not occur until sometime after this function has returned.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.For example, to get all saved items of the authenticated user:
for item in reddit.user.me().saved(limit=None): print(item.id)
- stream() praw.models.reddit.redditor.RedditorStream
Provide an instance of
RedditorStream
.Streams can be used to indefinitely retrieve new comments made by a redditor, like:
for comment in reddit.redditor("spez").stream.comments(): print(comment)
Additionally, new submissions can be retrieved via the stream. In the following example all submissions are fetched via the redditor u/spez:
for submission in reddit.redditor("spez").stream.submissions(): print(submission)
- submissions() SubListing
Provide an instance of
SubListing
for submission access.For example, to output the title’s of top 100 of all time submissions for u/spez try:
for submission in reddit.redditor("spez").submissions.top(time_filter="all"): print(submission.title)
- top(*, time_filter: str = 'all', **generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for top items.- Parameters:
time_filter – Can be one of:
"all"
,"day"
,"hour"
,"month"
,"week"
, or"year"
(default:"all"
).- Raises:
ValueError
iftime_filter
is invalid.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").top(time_filter="week") reddit.multireddit(redditor="samuraisam", name="programming").top(time_filter="day") reddit.redditor("spez").top(time_filter="month") reddit.redditor("spez").comments.top(time_filter="year") reddit.redditor("spez").submissions.top(time_filter="all") reddit.subreddit("all").top(time_filter="hour")
- trophies() List[praw.models.Trophy]
Return a list of the redditor’s trophies.
- Returns:
A list of
Trophy
objects. Return[]
if the redditor has no trophies.- Raises:
RedditAPIException
if the redditor doesn’t exist.
Usage:
for trophy in reddit.redditor("spez").trophies(): print(trophy.name) print(trophy.description)
- trust()
Add the
Redditor
to your whitelist of trusted users.Trusted users will always be able to send you PMs.
Example usage:
reddit.redditor("AaronSw").trust()
Use the
accept_pms
parameter ofPreferences.update()
to toggle youraccept_pms
setting between"everyone"
and"whitelisted"
. For example:# Accept private messages from everyone: reddit.user.preferences.update(accept_pms="everyone") # Only accept private messages from trusted users: reddit.user.preferences.update(accept_pms="whitelisted")
You may trust a user even if your
accept_pms
setting is switched to"everyone"
.Note
You are allowed to have a user on your blocked list and your friends list at the same time. However, you cannot trust a user who is on your blocked list.
See also
- unblock()
Unblock the
Redditor
.For example, to unblock
Redditor
u/spez:reddit.redditor("spez").unblock()
- unfriend()
Unfriend the
Redditor
.For example, to unfriend
Redditor
u/spez:reddit.redditor("spez").unfriend()
- upvoted(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Comment | praw.models.Submission]
Return a
ListingGenerator
for items the user has upvoted.- Returns:
A
ListingGenerator
object which yieldsComment
orSubmission
objects the user has upvoted.- Raises:
prawcore.Forbidden
if the user is not authorized to access the list.Note
Since this function returns a
ListingGenerator
the exception may not occur until sometime after this function has returned.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.For example, to get all upvoted items of the authenticated user:
for item in reddit.user.me().upvoted(): print(item.id)
Submission
- class praw.models.Submission(reddit: praw.Reddit, id: str | None = None, url: str | None = None, _data: Dict[str, Any] | None = None)
A class for submissions to Reddit.
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
author
Provides an instance of
Redditor
.author_flair_text
The text content of the author’s flair, or
None
if not flaired.clicked
Whether or not the submission has been clicked by the client.
comments
Provides an instance of
CommentForest
.created_utc
Time the submission was created, represented in Unix Time.
distinguished
Whether or not the submission is distinguished.
edited
Whether or not the submission has been edited.
id
ID of the submission.
is_original_content
Whether or not the submission has been set as original content.
is_self
Whether or not the submission is a selfpost (text-only).
link_flair_template_id
The link flair’s ID.
link_flair_text
The link flair’s text content, or
None
if not flaired.locked
Whether or not the submission has been locked.
name
Fullname of the submission.
num_comments
The number of comments on the submission.
over_18
Whether or not the submission has been marked as NSFW.
permalink
A permalink for the submission.
poll_data
A
PollData
object representing the data of this submission, if it is a poll submission.saved
Whether or not the submission is saved.
score
The number of upvotes for the submission.
selftext
The submissions’ selftext - an empty string if a link post.
spoiler
Whether or not the submission has been marked as a spoiler.
stickied
Whether or not the submission is stickied.
subreddit
Provides an instance of
Subreddit
.title
The title of the submission.
upvote_ratio
The percentage of upvotes from all votes on the submission.
url
The URL the submission links to, or the permalink if a selfpost.
- __init__(reddit: praw.Reddit, id: str | None = None, url: str | None = None, _data: Dict[str, Any] | None = None)
Initialize a
Submission
instance.- Parameters:
reddit – An instance of
Reddit
.id – A reddit base36 submission ID, e.g.,
"2gmzqe"
.url – A URL supported by
id_from_url()
.
Either
id
orurl
can be provided, but not both.
- award(*, gild_type: str = 'gid_2', is_anonymous: bool = True, message: str = None) dict
Award the author of the item.
- Parameters:
gild_type – Type of award to give. See table below for currently know global award types.
is_anonymous – If
True
, the authenticated user’s username will not be revealed to the recipient.message – Message to include with the award.
- Returns:
A dict containing info similar to what is shown below:
{ "subreddit_balance": 85260, "treatment_tags": [], "coins": 8760, "gildings": {"gid_1": 0, "gid_2": 1, "gid_3": 0}, "awarder_karma_received": 4, "all_awardings": [ { "giver_coin_reward": 0, "subreddit_id": None, "is_new": False, "days_of_drip_extension": 0, "coin_price": 75, "id": "award_9663243a-e77f-44cf-abc6-850ead2cd18d", "penny_donate": 0, "coin_reward": 0, "icon_url": "https://www.redditstatic.com/gold/awards/icon/SnooClappingPremium_512.png", "days_of_premium": 0, "icon_height": 512, "tiers_by_required_awardings": None, "icon_width": 512, "static_icon_width": 512, "start_date": None, "is_enabled": True, "awardings_required_to_grant_benefits": None, "description": "For an especially amazing showing.", "end_date": None, "subreddit_coin_reward": 0, "count": 1, "static_icon_height": 512, "name": "Bravo Grande!", "icon_format": "APNG", "award_sub_type": "PREMIUM", "penny_price": 0, "award_type": "global", "static_icon_url": "https://i.redd.it/award_images/t5_q0gj4/59e02tmkl4451_BravoGrande-Static.png", } ], }
Warning
Requires the authenticated user to own Reddit Coins. Calling this method will consume Reddit Coins.
To award the gold award anonymously do:
comment = reddit.comment("dkk4qjd") comment.award() submission = reddit.submission("8dmv8z") submission.award()
To award the platinum award with the message ‘Nice!’ and reveal your username to the recipient do:
comment = reddit.comment("dkk4qjd") comment.award(gild_type="gild_3", message="Nice!", is_anonymous=False) submission = reddit.submission("8dmv8z") submission.award(gild_type="gild_3", message="Nice!", is_anonymous=False)
This is a list of known global awards (as of 11/08/2021)
Name
Icon
Gild Type
Description
Cost
Silver
gid_1
Shows the Silver Award… and that’s it.
100
Gold
gid_2
Gives 100 Reddit Coins and a week of r/lounge access and ad-free browsing.
500
Platinum
gid_3
Gives 700 Reddit Coins and a month of r/lounge access and ad-free browsing.
1800
LOVE!
award_5eac457f-ebac-449b-93a7-eb17b557f03c
When you follow your heart, love is the answer
20
Starstruck
award_abb865cf-620b-4219-8777-3658cf9091fb
Can’t stop seeing stars
20
All-Seeing Upvote
award_b4ff447e-05a5-42dc-9002-63568807cfe6
A glowing commendation for all to see
30
Narwhal Salute
award_a2506925-fc82-4d6c-ae3b-b7217e09d7f0
A golden splash of respect
30
Wholesome Seal of Approval
award_c4b2e438-16bb-4568-88e7-7893b7662944
A glittering stamp for a feel-good thing
30
Ally
award_69c94eb4-d6a3-48e7-9cf2-0f39fed8b87c
Listen, get educated, and get involved.
50
Take My Energy
award_02d9ab2c-162e-4c01-8438-317a016ed3d9
I’m in this with you.
50
Wearing is Caring
award_80d4d339-95d0-43ac-b051-bc3fe0a9bab8
Keep the community and yourself healthy and happy.
50
Facepalm
award_b1b44fa1-8179-4d84-a9ed-f25bb81f1c5f
Lowers face into palm
70
Snek
award_99d95969-6100-45b2-b00c-0ec45ae19596
A smol, delicate danger noodle.
70
Tree Hug
award_b92370bb-b7de-4fb3-9608-c5b4a22f714a
Show nature some love.
70
Bravo Grande!
award_9663243a-e77f-44cf-abc6-850ead2cd18d
For an especially amazing showing.
75
Party Train
award_75f9bc56-eba3-4988-a1af-aec974404a0b
All aboard! Every five Party Train Awards gives the author 100 Reddit Coins and a week of r/lounge access and ad-free browsing. Rack up the awards and watch the train level-up!
75
Take My Power
award_92cb6518-a71a-4217-9f8f-7ecbd7ab12ba
Add my power to yours.
75
Defeated
award_58ef8551-8c27-4f03-afa5-748432194e3d
The process of taking a painful L
80
Hugz
award_8352bdff-3e03-4189-8a08-82501dd8f835
Everything is better with a good hug
80
‘MURICA
award_869d4135-8738-41e5-8630-de593b4f049f
Did somebody say ‘Murica?
100
Burning Cash
award_abcdefe4-c92f-4c66-880f-425962d17098
I don’t need it, I don’t even necessarily want it, but I’ve got some cash to burn so I’m gonna get it.
100
Dread
award_81cf5c92-8500-498c-9c94-3e4034cece0a
Staring into the abyss and it’s staring right back
100
Evil Cackle
award_483d8e29-bbe5-404e-a09a-c2d7b16c4fff
Laugh like a supervillain
100
Glow Up
award_01178870-6a4f-4172-8f36-9ed5092ee4f9
You look amazing, glowing, incredible!
100
Heartwarming
award_19860e30-3331-4bac-b3d1-bd28de0c7974
I needed this today
100
I am disappoint
award_03c4f93d-efc7-463b-98a7-c01814462ab0
I’m not mad, I’m just disappointed.
100
I’ll Drink to That
award_3267ca1c-127a-49e9-9a3d-4ba96224af18
Let’s sip to good health and good company
100
Keep Calm
award_1da6ff27-7c0d-4524-9954-86e5cda5fcac
Stop, chill, relax
100
Kiss
award_1e516e18-cbee-4668-b338-32d5530f91fe
You deserve a smooch
100
Lawyer Up
award_ae89e420-c4a5-47b8-a007-5dacf1c0f0d4
OBJECTION!
100
Masterpiece
award_b4072731-c0fb-4440-adc7-1063d6a5e6a0
C’est magnifique
100
Shocked
award_fbe9527a-adb3-430e-af1a-5fd3489e641b
I’m genuinely flabbergasted.
100
Tearing Up
award_43f3bf99-92d6-47ab-8205-130d26e7929f
This hits me right in the feels
100
Yummy
award_ae7f17fb-6538-4c75-9ff4-5f48b4cdaa94
That looks so good
100
Faith In Humanity Restored
award_611ff347-196b-4a14-ad4b-0076f2d8f9d2
This goes a long way to restore my faith in the people of Earth
125
Wholesome
award_5f123e3d-4f48-42f4-9c11-e98b566d5897
When you come across a feel-good thing.
125
Beating Heart
award_0d762fb3-17e4-4477-ab6b-9770b71b493c
My valentine makes my heart beat out of my chest.
150
Bless Up
award_77ba55a2-c33c-4351-ac49-807455a80148
Prayers up for the blessed.
150
Buff Doge
award_c42dc561-0b41-40b6-a23d-ef7e110e739e
So buff, wow
150
Cake
award_5fb42699-4911-42a2-884c-6fc8bdc36059
Did someone say… cake?
150
Helpful
award_f44611f1-b89e-46dc-97fe-892280b13b82
Thank you stranger. Shows the award.
150
I Shy
award_beccaae0-d745-44f9-bc5c-3c9f8117699b
No matter how hard I try, I’m too shy to confess my love!
150
Press F
award_88fdcafc-57a0-48db-99cc-76276bfaf28b
To pay respects.
150
Take My Money
award_a7f9cbd7-c0f1-4569-a913-ebf8d18de00b
I’m buying what you’re selling
150
2020 Veteran
award_f0875744-15da-41ee-8591-b88e5a88c430
A reward for making it through the most topsey- turvey year anyone can remember. Gives 100 coins to the recipient.
200
Baby Snoo
award_4d880932-4b45-4723-a964-5d749ace4df2
Baby Snoo is back and cuter than ever
200
Giggle
award_e813313c-1002-49bf-ac37-e966710f605f
Innocent laughter
200
Got the W
award_8dc476c7-1478-4d41-b940-f139e58f7756
200
I’d Like to Thank…
award_1703f934-cf44-40cc-a96d-3729d0b48262
My kindergarten teacher, my cat, my mom, and you.
200
I’m Deceased
award_b28d9565-4137-433d-bb65-5d4aa82ade4c
Call an ambulance, I’m laughing too hard.
200
Looking
award_4922c1be-3646-4d62-96ea-19a56798df51
I can’t help but look.
200
Lurking
award_59ae34c0-14c8-4b16-a527-e157fac0a6c7
Just seeing what’s going on
200
Plus One
award_f7562045-905d-413e-9ed2-0a16d4bfe349
You officially endorse and add your voice to the crowd.
200
Sidevote
award_cd297f1a-8368-4f5a-acb8-6ec96fc6e8d6
Not an upvote, not a downvote, just an in-the- middle sidevote.
200
Stone Face
award_2c3bb816-f6fc-46e8-aaf7-2b196afffada
You got me stone faced
200
Stonks Falling
award_9ee30a8f-463e-4ef7-9da9-a09f270ec026
Losing value fast.
200
Stonks Rising
award_d125d124-5c03-490d-af3d-d07c462003da
To the MOON.
200
1UP
award_11be92ba-509e-46d3-991b-593239006521
Extra life
250
Are You Serious?
award_ca888c60-cd8c-4875-97f1-b536dc35a9a5
Are you being serious right now?
250
Are You Winning?
award_5641bae4-e690-4832-a498-4bd78da8b2b1
Well, are you?
250
Awesome Answer
award_2adc49e8-d6c9-4923-9293-2bfab1648569
For a winning take and the kind soul who nails a question. Gives %{coin_symbol}100 Coins to both the author and the community.
250
Big Brain Time
award_e71deb9c-a466-4743-9a73-48771c000077
2000 IQ
250
Calculating
award_242c4f2c-6f1c-4387-9b5b-d0249d6ecd36
Something isn’t adding up
250
Confetti
award_1671746c-49e2-4cdd-be4e-ec8892434278
Party time, shower them with sparkly paper
250
Doom
award_e03a0c52-56b5-45df-bd6f-5f2da10cfdc5
A sense of impending doom
250
Duck Dance
award_c3e02835-9444-4a7f-9e7f-206e8bf0ed99
He do be dancing though
250
Endless Coolness
award_aac76dbe-2272-4fad-ac06-c077d2d9049e
Cool to the infinity
250
It’s Cute!
award_cc540de7-dfdb-4a68-9acf-6f9ce6b17d21
You made me UwU.
250
Laser Eyes
award_e1ed6fb9-f23e-4cb4-aad9-70c83e4b1924
250
Mind Blown
award_9583d210-a7d0-4f3c-b0c7-369ad579d3d4
When a thing immediately combusts your brain. Gives %{coin_symbol}100 Coins to both the author and the community.
250
Original
award_d306c865-0d49-4a36-a1ab-a4122a0e3480
When something new and creative wows you. Gives %{coin_symbol}100 Coins to both the author and the community.
250
Pranked!
award_e2250c69-8bd9-4e2f-8fb7-e6630e6c5c8a
Cake direct to face
250
Respect
award_c8503d66-6450-40c5-963f-35ced99bd361
Tip of my hat to you
250
That Smile
award_e11fc833-31fe-4c43-bde8-aead928b4b70
Cute but creepy
250
Timeless Beauty
award_31260000-2f4a-4b40-ad20-f5aa46a577bf
Beauty that’s forever. Gives %{coin_symbol}100 Coins each to the author and the community.
250
Today I Learned
award_a67d649d-5aa5-407e-a98b-32fd9e3a9696
The more you know… Gives %{coin_symbol}100 Coins to both the author and the community.
250
Vibing
award_3f4e6f36-dacc-4919-b170-9d0201cd258f
I’m catching the vibration
250
Wink Wink
award_a8196b8f-1a76-4902-b324-b9473854dade
nudge, nudge
250
Woah Dude
award_d88c5520-18d0-4ef0-9a36-41f8617584b0
Sometimes you’re left just going WOAH…
250
Yas Queen
award_d48aad4b-286f-4a3a-bb41-ec05b3cd87cc
YAAAAAAAAAAASSS.
250
You Dropped This
award_92d8645c-de2c-44ae-8cd7-7b0c6ab25297
King
250
hehehehe
award_435a5692-f508-4b31-8083-ddc576f26ad3
That’s a little funny
250
Blow a Kiss
award_9ef35273-7942-4199-a76a-3d37f3b52a2e
smooch
300
Coin Gift
award_3dd248bc-3438-4c5b-98d4-24421fd6d670
Give the gift of %{coin_symbol}250 Reddit Coins.
300
Crab Rave
award_f7a4fd5e-7cd1-4c11-a1c9-c18d05902e81
[Happy crab noises]
300
GOAT
award_cc299d65-77de-4828-89de-708b088349a0
Historical anomaly - greatest in eternity.
300
Heartbreak
award_dc85c1f3-b5aa-4970-9a5d-40304252f79e
Suffering from a broken heart
300
Rocket Like
award_28e8196b-d4e9-45bc-b612-cd4c7d3ed4b3
When an upvote just isn’t enough, smash the Rocket Like.
300
Table Flip
award_3e000ecb-c1a4-49dc-af14-c8ac2029ca97
ARGH!
300
This
award_68ba1ee3-9baf-4252-be52-b808c1e8bdc4
THIS right here! Join together to give multiple This awards and see the award evolve in its display and shower benefits for the recipient. For every 3 This awards given to a post or comment, the author will get 250 coins.
300
Updoot
award_725b427d-320b-4d02-8fb0-8bb7aa7b78aa
Sometimes you just got to doot.
300
Wait What?
award_a3b7d374-68b4-4c77-8a57-e11fd6f26c06
Hold up, what was that?
300
Spit-take
award_3409a4c0-ba69-43a0-be9f-27bc27c159cc
Shower them with laughs
325
Super Heart Eyes
award_6220ecfe-4552-4949-aa13-fb1fb7db537c
When the love is out of control.
325
Table Slap
award_9f928aff-c9f5-4e7e-aa91-8619dce60f1c
When laughter meets percussion
325
To The Stars
award_2bc47247-b107-44a8-a78c-613da21869ff
Boldly go where we haven’t been in a long, long time.
325
Into the Magic Portal
award_2ff1fdd0-ff73-47e6-a43c-bde6d4de8fbd
Hope to make it to the other side.
350
Out of the Magic Portal
award_7fe72f36-1141-4a39-ba76-0d481889b390
That was fun, but I’m glad to be back
350
Bravo!
award_84276b1e-cc8f-484f-a19c-be6c09adc1a5
An amazing showing.
400
Doot 🎵 Doot
award_5b39e8fd-7a58-4cbe-8ca0-bdedd5ed1f5a
Sometimes you just got to dance with the doots.
400
Bless Up (Pro)
award_43c43a35-15c5-4f73-91ef-fe538426435a
Prayers up for the blessed. Gives %{coin_symbol}100 Coins to both the author and the community.
500
Brighten My Day
award_9591a26e-b2e4-4ef2-bed4-28ff69246691
The clouds part and the sun shines through. Use the Brighten My Day Award to highlight comments that are a ray of sunshine.
500
Eureka!
award_65f78ca2-45d8-4cb6-bf79-a67beadf2e47
Now that is a bright idea. Use the Eureka Award to highlight comments that are brilliant.
500
Heart Eyes
award_a9009ea5-1a36-42ae-aab2-5967563ee054
For love at first sight. Gives %{coin_symbol}100 Coins to both the author and the community.
500
Helpful (Pro)
award_2ae56630-cfe0-424e-b810-4945b9145358
Thank you stranger. Gives %{coin_symbol}100 Coins to both the author and the community.
500
Made Me Smile
award_a7a04d6a-8dd8-41bb-b906-04fa8f144014
When you’re smiling before you know it. Gives %{coin_symbol}100 Coins to both the author and the community.
500
Starry
award_0e957fb0-c8f1-4ba1-a8ef-e1e524b60d7d
Use the Starry Award to highlight comments that deserve to stand out from the crowd.
500
Wholesome (Pro)
award_1f0462ee-18f5-4f33-89cf-f1f79336a452
When you come across a feel-good thing. Gives %{coin_symbol}100 Coins to both the author and the community.
500
Pot o’ Coins
award_35c78e6e-507b-4f1d-b3d8-ed43840909a8
The treasure at the end of the rainbow. Gives the author 800 Coins to do with as they please.
1000
Argentium
award_4ca5a4e6-8873-4ac5-99b9-71b1d5161a91
Latin for distinguished, this award shimmers like silver and is stronger than steel. It’s for those who deserve outsized recognition. Gives 2,500 Reddit Coins and three months of r/lounge access and ad-free browsing.
20000
Ternion All-Powerful
award_2385c499-a1fb-44ec-b9b7-d260f3dc55de
Legendary level, this award is a no holds barred celebration of something that hits you in the heart, mind, and soul. Some might call it unachievanium. Gives 5,000 Reddit Coins and six months of r/lounge access and ad-free browsing.
50000
- clear_vote()
Clear the authenticated user’s vote on the object.
Note
Votes must be cast by humans. That is, API clients proxying a human’s action one-for-one are OK, but bots deciding how to vote on content or amplifying a human’s vote are not. See the reddit rules for more details on what constitutes vote manipulation. [Ref]
Example usage:
submission = reddit.submission("5or86n") submission.clear_vote() comment = reddit.comment("dxolpyc") comment.clear_vote()
- property comments: CommentForest
Provide an instance of
CommentForest
.This attribute can be used, for example, to obtain a flat list of comments, with any
MoreComments
removed:submission.comments.replace_more(limit=0) comments = submission.comments.list()
Sort order and comment limit can be set with the
comment_sort
andcomment_limit
attributes before comments are fetched, including any call toreplace_more()
:submission.comment_sort = "new" comments = submission.comments.list()
Note
The appropriate values for
"comment_sort"
include"confidence"
,"controversial"
,"new"
,"old"
,"q&a"
, and"top"
See Extracting comments with PRAW for more on working with a
CommentForest
.
- crosspost(subreddit: praw.models.Subreddit, *, flair_id: str | None = None, flair_text: str | None = None, nsfw: bool = False, send_replies: bool = True, spoiler: bool = False, title: str | None = None) praw.models.Submission
Crosspost the submission to a subreddit.
Note
Be aware you have to be subscribed to the target subreddit.
- Parameters:
subreddit – Name of the subreddit or
Subreddit
object to crosspost into.flair_id – The flair template to select (default:
None
).flair_text – If the template’s
flair_text_editable
value isTrue
, this value will set a custom text (default:None
).nsfw – Whether the submission should be marked NSFW (default:
False
).send_replies – When
True
, messages will be sent to the created submission’s author when comments are made to the submission (default:True
).spoiler – Whether the submission should be marked as a spoiler (default:
False
).title – Title of the submission. Will use this submission’s title if
None
(default:None
).
- Returns:
A
Submission
object for the newly created submission.
Example usage:
submission = reddit.submission("5or86n") cross_post = submission.crosspost("learnprogramming", send_replies=False)
See also
- delete()
Delete the object.
Example usage:
comment = reddit.comment("dkk4qjd") comment.delete() submission = reddit.submission("8dmv8z") submission.delete()
- disable_inbox_replies()
Disable inbox replies for the item.
Example usage:
comment = reddit.comment("dkk4qjd") comment.disable_inbox_replies() submission = reddit.submission("8dmv8z") submission.disable_inbox_replies()
See also
- downvote()
Downvote the object.
Note
Votes must be cast by humans. That is, API clients proxying a human’s action one-for-one are OK, but bots deciding how to vote on content or amplifying a human’s vote are not. See the reddit rules for more details on what constitutes vote manipulation. [Ref]
Example usage:
submission = reddit.submission("5or86n") submission.downvote() comment = reddit.comment("dxolpyc") comment.downvote()
See also
- duplicates(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Submission]
Return a
ListingGenerator
for the submission’s duplicates.Additional keyword arguments are passed in the initialization of
ListingGenerator
.Example usage:
submission = reddit.submission("5or86n") for duplicate in submission.duplicates(): # process each duplicate ...
See also
- edit(body: str) praw.models.Comment | praw.models.Submission
Replace the body of the object with
body
.- Parameters:
body – The Markdown formatted content for the updated object.
- Returns:
The current instance after updating its attributes.
Example usage:
comment = reddit.comment("dkk4qjd") # construct the text of an edited comment # by appending to the old body: edited_body = comment.body + "Edit: thanks for the gold!" comment.edit(edited_body)
- enable_inbox_replies()
Enable inbox replies for the item.
Example usage:
comment = reddit.comment("dkk4qjd") comment.enable_inbox_replies() submission = reddit.submission("8dmv8z") submission.enable_inbox_replies()
See also
- flair() SubmissionFlair
Provide an instance of
SubmissionFlair
.This attribute is used to work with flair as a regular user of the subreddit the submission belongs to. Moderators can directly use
flair()
.For example, to select an arbitrary editable flair text (assuming there is one) and set a custom value try:
choices = submission.flair.choices() template_id = next(x for x in choices if x["flair_text_editable"])["flair_template_id"] submission.flair.select(template_id, text="my custom value")
- property fullname: str
Return the object’s fullname.
A fullname is an object’s kind mapping like
t3
followed by an underscore and the object’s base36 ID, e.g.,t1_c5s96e0
.
- hide(*, other_submissions: List[praw.models.Submission] | None = None)
Hide
Submission
.- Parameters:
other_submissions – When provided, additionally hide this list of
Submission
instances as part of a single request (default:None
).
Example usage:
submission = reddit.submission("5or86n") submission.hide()
See also
- static id_from_url(url: str) str
Return the ID contained within a submission URL.
- Parameters:
url –
A url to a submission in one of the following formats (http urls will also work):
"https://redd.it/2gmzqe"
"https://reddit.com/comments/2gmzqe/"
"https://www.reddit.com/r/redditdev/comments/2gmzqe/praw_https/"
"https://www.reddit.com/gallery/2gmzqe"
- Raises:
InvalidURL
ifurl
is not a valid submission URL.
- mark_visited()
Mark submission as visited.
This method requires a subscription to reddit premium.
Example usage:
submission = reddit.submission("5or86n") submission.mark_visited()
- mod() SubmissionModeration
Provide an instance of
SubmissionModeration
.Example usage:
submission = reddit.submission("8dmv8z") submission.mod.approve()
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit) Any
Return an instance of
cls
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.
- reply(body: str) praw.models.Comment | praw.models.Message | None
Reply to the object.
- Parameters:
body – The Markdown formatted content for a comment.
- Returns:
A
Comment
orMessage
object for the newly created comment or message orNone
if Reddit doesn’t provide one.- Raises:
prawcore.exceptions.Forbidden
when attempting to reply to some items, such as locked submissions/comments or non-replyable messages.
A
None
value can be returned if the target is a comment or submission in a quarantined subreddit and the authenticated user has not opt-ed into viewing the content. When this happens the comment will be successfully created on Reddit and can be retried by drawing the comment from the user’s comment history.Example usage:
submission = reddit.submission("5or86n") submission.reply("reply") comment = reddit.comment("dxolpyc") comment.reply("reply")
- report(reason: str)
Report this object to the moderators of its subreddit.
- Parameters:
reason – The reason for reporting.
- Raises:
RedditAPIException
ifreason
is longer than 100 characters.
Example usage:
submission = reddit.submission("5or86n") submission.report("report reason") comment = reddit.comment("dxolpyc") comment.report("report reason")
- save(*, category: str | None = None)
Save the object.
- Parameters:
category – The category to save to. If the authenticated user does not have Reddit Premium this value is ignored by Reddit (default:
None
).
Example usage:
submission = reddit.submission("5or86n") submission.save(category="view later") comment = reddit.comment("dxolpyc") comment.save()
See also
- property shortlink: str
Return a shortlink to the submission.
For example, https://redd.it/eorhm is a shortlink for https://www.reddit.com/r/announcements/comments/eorhm/reddit_30_less_typing/.
- unhide(*, other_submissions: List[praw.models.Submission] | None = None)
Unhide
Submission
.- Parameters:
other_submissions – When provided, additionally unhide this list of
Submission
instances as part of a single request (default:None
).
Example usage:
submission = reddit.submission("5or86n") submission.unhide()
See also
- unsave()
Unsave the object.
Example usage:
submission = reddit.submission("5or86n") submission.unsave() comment = reddit.comment("dxolpyc") comment.unsave()
See also
- upvote()
Upvote the object.
Note
Votes must be cast by humans. That is, API clients proxying a human’s action one-for-one are OK, but bots deciding how to vote on content or amplifying a human’s vote are not. See the reddit rules for more details on what constitutes vote manipulation. [Ref]
Example usage:
submission = reddit.submission("5or86n") submission.upvote() comment = reddit.comment("dxolpyc") comment.upvote()
See also
Subreddit
- class praw.models.Subreddit(reddit: praw.Reddit, display_name: str | None = None, _data: Dict[str, Any] | None = None)
A class for Subreddits.
To obtain an instance of this class for r/test execute:
subreddit = reddit.subreddit("test")
While r/all is not a real subreddit, it can still be treated like one. The following outputs the titles of the 25 hottest submissions in r/all:
for submission in reddit.subreddit("all").hot(limit=25): print(submission.title)
Multiple subreddits can be combined with a
+
like so:for submission in reddit.subreddit("redditdev+learnpython").top(time_filter="all"): print(submission)
Subreddits can be filtered from combined listings as follows.
Note
These filters are ignored by certain methods, including
comments
,gilded()
, andSubredditStream.comments()
.for submission in reddit.subreddit("all-redditdev").new(): print(submission)
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
can_assign_link_flair
Whether users can assign their own link flair.
can_assign_user_flair
Whether users can assign their own user flair.
created_utc
Time the subreddit was created, represented in Unix Time.
description
Subreddit description, in Markdown.
description_html
Subreddit description, in HTML.
display_name
Name of the subreddit.
id
ID of the subreddit.
name
Fullname of the subreddit.
over18
Whether the subreddit is NSFW.
public_description
Description of the subreddit, shown in searches and on the “You must be invited to visit this community” page (if applicable).
spoilers_enabled
Whether the spoiler tag feature is enabled.
subscribers
Count of subscribers.
user_is_banned
Whether the authenticated user is banned.
user_is_moderator
Whether the authenticated user is a moderator.
user_is_subscriber
Whether the authenticated user is subscribed.
Note
Trying to retrieve attributes of quarantined or private subreddits will result in a 403 error. Trying to retrieve attributes of a banned subreddit will result in a 404 error.
- __init__(reddit: praw.Reddit, display_name: str | None = None, _data: Dict[str, Any] | None = None)
Initialize a
Subreddit
instance.- Parameters:
reddit – An instance of
Reddit
.display_name – The name of the subreddit.
Note
This class should not be initialized directly. Instead, obtain an instance via:
reddit.subreddit("test")
- banned() praw.models.reddit.subreddit.SubredditRelationship
Provide an instance of
SubredditRelationship
.For example, to ban a user try:
reddit.subreddit("test").banned.add("spez", ban_reason="...")
To list the banned users along with any notes, try:
for ban in reddit.subreddit("test").banned(): print(f"{ban}: {ban.note}")
- collections() praw.models.reddit.collections.SubredditCollections
Provide an instance of
SubredditCollections
.To see the permalinks of all
Collection
s that belong to a subreddit, try:for collection in reddit.subreddit("test").collections: print(collection.permalink)
To get a specific
Collection
by its UUID or permalink, use one of the following:collection = reddit.subreddit("test").collections("some_uuid") collection = reddit.subreddit("test").collections( permalink="https://reddit.com/r/SUBREDDIT/collection/some_uuid" )
- comments() CommentHelper
Provide an instance of
CommentHelper
.For example, to output the author of the 25 most recent comments of r/test execute:
for comment in reddit.subreddit("test").comments(limit=25): print(comment.author)
- contributor() praw.models.reddit.subreddit.ContributorRelationship
Provide an instance of
ContributorRelationship
.Contributors are also known as approved submitters.
To add a contributor try:
reddit.subreddit("test").contributor.add("spez")
- controversial(*, time_filter: str = 'all', **generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for controversial items.- Parameters:
time_filter – Can be one of:
"all"
,"day"
,"hour"
,"month"
,"week"
, or"year"
(default:"all"
).- Raises:
ValueError
iftime_filter
is invalid.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").controversial(time_filter="week") reddit.multireddit(redditor="samuraisam", name="programming").controversial( time_filter="day" ) reddit.redditor("spez").controversial(time_filter="month") reddit.redditor("spez").comments.controversial(time_filter="year") reddit.redditor("spez").submissions.controversial(time_filter="all") reddit.subreddit("all").controversial(time_filter="hour")
- emoji() SubredditEmoji
Provide an instance of
SubredditEmoji
.This attribute can be used to discover all emoji for a subreddit:
for emoji in reddit.subreddit("test").emoji: print(emoji)
A single emoji can be lazily retrieved via:
reddit.subreddit("test").emoji["emoji_name"]
Note
Attempting to access attributes of a nonexistent emoji will result in a
ClientException
.
- filters() praw.models.reddit.subreddit.SubredditFilters
Provide an instance of
SubredditFilters
.For example, to add a filter, run:
reddit.subreddit("all").filters.add("test")
- flair() praw.models.reddit.subreddit.SubredditFlair
Provide an instance of
SubredditFlair
.Use this attribute for interacting with a
Subreddit
’s flair. For example, to list all the flair for a subreddit which you have theflair
moderator permission on try:for flair in reddit.subreddit("test").flair(): print(flair)
Flair templates can be interacted with through this attribute via:
for template in reddit.subreddit("test").flair.templates: print(template)
- property fullname: str
Return the object’s fullname.
A fullname is an object’s kind mapping like
t3
followed by an underscore and the object’s base36 ID, e.g.,t1_c5s96e0
.
- gilded(**generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for gilded items.Additional keyword arguments are passed in the initialization of
ListingGenerator
.For example, to get gilded items in r/test:
for item in reddit.subreddit("test").gilded(): print(item.id)
- hot(**generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for hot items.Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").hot() reddit.multireddit(redditor="samuraisam", name="programming").hot() reddit.redditor("spez").hot() reddit.redditor("spez").comments.hot() reddit.redditor("spez").submissions.hot() reddit.subreddit("all").hot()
- message(*, from_subreddit: praw.models.Subreddit | str | None = None, message: str, subject: str)
Send a message to a
Redditor
or aSubreddit
’s moderators (modmail).- Parameters:
from_subreddit –
A
Subreddit
instance or string to send the message from. When provided, messages are sent from the subreddit rather than from the authenticated user.Note
The authenticated user must be a moderator of the subreddit and have the
mail
moderator permission.message – The message content.
subject – The subject of the message.
For example, to send a private message to u/spez, try:
reddit.redditor("spez").message(subject="TEST", message="test message from PRAW")
To send a message to u/spez from the moderators of r/test try:
reddit.redditor("spez").message( subject="TEST", message="test message from r/test", from_subreddit="test" )
To send a message to the moderators of r/test, try:
reddit.subreddit("test").message(subject="TEST", message="test PM from PRAW")
- mod() SubredditModeration
Provide an instance of
SubredditModeration
.For example, to accept a moderation invite from r/test:
reddit.subreddit("test").mod.accept_invite()
- moderator() praw.models.reddit.subreddit.ModeratorRelationship
Provide an instance of
ModeratorRelationship
.For example, to add a moderator try:
reddit.subreddit("test").moderator.add("spez")
To list the moderators along with their permissions try:
for moderator in reddit.subreddit("test").moderator(): print(f"{moderator}: {moderator.mod_permissions}")
- modmail() praw.models.reddit.subreddit.Modmail
Provide an instance of
Modmail
.For example, to send a new modmail from r/test to u/spez with the subject
"test"
along with a message body of"hello"
:reddit.subreddit("test").modmail.create(subject="test", body="hello", recipient="spez")
- muted() praw.models.reddit.subreddit.SubredditRelationship
Provide an instance of
SubredditRelationship
.For example, muted users can be iterated through like so:
for mute in reddit.subreddit("test").muted(): print(f"{mute}: {mute.date}")
- new(**generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for new items.Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").new() reddit.multireddit(redditor="samuraisam", name="programming").new() reddit.redditor("spez").new() reddit.redditor("spez").comments.new() reddit.redditor("spez").submissions.new() reddit.subreddit("all").new()
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit) Any
Return an instance of
cls
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.
- post_requirements() Dict[str, str | int | bool]
Get the post requirements for a subreddit.
- Returns:
A dict with the various requirements.
The returned dict contains the following keys:
domain_blacklist
body_restriction_policy
domain_whitelist
title_regexes
body_blacklisted_strings
body_required_strings
title_text_min_length
is_flair_required
title_text_max_length
body_regexes
link_repost_age
body_text_min_length
link_restriction_policy
body_text_max_length
title_required_strings
title_blacklisted_strings
guidelines_text
guidelines_display_policy
For example, to fetch the post requirements for r/test:
print(reddit.subreddit("test").post_requirements)
- quaran() praw.models.reddit.subreddit.SubredditQuarantine
Provide an instance of
SubredditQuarantine
.This property is named
quaran
becausequarantine
is a subreddit attribute returned by Reddit to indicate whether or not a subreddit is quarantined.To opt-in into a quarantined subreddit:
reddit.subreddit("test").quaran.opt_in()
- random() praw.models.Submission | None
Return a random
Submission
.Returns
None
on subreddits that do not support the random feature. One example, at the time of writing, is r/wallpapers.For example, to get a random submission off of r/AskReddit:
submission = reddit.subreddit("AskReddit").random() print(submission.title)
- random_rising(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Submission]
Return a
ListingGenerator
for random rising submissions.Additional keyword arguments are passed in the initialization of
ListingGenerator
.For example, to get random rising submissions for r/test:
for submission in reddit.subreddit("test").random_rising(): print(submission.title)
- rising(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Submission]
Return a
ListingGenerator
for rising submissions.Additional keyword arguments are passed in the initialization of
ListingGenerator
.For example, to get rising submissions for r/test:
for submission in reddit.subreddit("test").rising(): print(submission.title)
- rules() SubredditRules
Provide an instance of
SubredditRules
.Use this attribute for interacting with a
Subreddit
’s rules.For example, to list all the rules for a subreddit:
for rule in reddit.subreddit("test").rules: print(rule)
Moderators can also add rules to the subreddit. For example, to make a rule called
"No spam"
in r/test:reddit.subreddit("test").rules.mod.add( short_name="No spam", kind="all", description="Do not spam. Spam bad" )
- search(query: str, *, sort: str = 'relevance', syntax: str = 'lucene', time_filter: str = 'all', **generator_kwargs: Any) Iterator[praw.models.Submission]
Return a
ListingGenerator
for items that matchquery
.- Parameters:
query – The query string to search for.
sort – Can be one of:
"relevance"
,"hot"
,"top"
,"new"
, or"comments"
. (default:"relevance"
).syntax – Can be one of:
"cloudsearch"
,"lucene"
, or"plain"
(default:"lucene"
).time_filter – Can be one of:
"all"
,"day"
,"hour"
,"month"
,"week"
, or"year"
(default:"all"
).
For more information on building a search query see: https://www.reddit.com/wiki/search
For example, to search all subreddits for
"praw"
try:for submission in reddit.subreddit("all").search("praw"): print(submission.title)
- sticky(*, number: int = 1) praw.models.Submission
Return a
Submission
object for a sticky of the subreddit.- Parameters:
number – Specify which sticky to return. 1 appears at the top (default:
1
).- Raises:
prawcore.NotFound
if the sticky does not exist.
For example, to get the stickied post on r/test:
reddit.subreddit("test").sticky()
- stream() praw.models.reddit.subreddit.SubredditStream
Provide an instance of
SubredditStream
.Streams can be used to indefinitely retrieve new comments made to a subreddit, like:
for comment in reddit.subreddit("test").stream.comments(): print(comment)
Additionally, new submissions can be retrieved via the stream. In the following example all submissions are fetched via the special r/all:
for submission in reddit.subreddit("all").stream.submissions(): print(submission)
- stylesheet() praw.models.reddit.subreddit.SubredditStylesheet
Provide an instance of
SubredditStylesheet
.For example, to add the css data
.test{color:blue}
to the existing stylesheet:subreddit = reddit.subreddit("test") stylesheet = subreddit.stylesheet() stylesheet.stylesheet += ".test{color:blue}" subreddit.stylesheet.update(stylesheet.stylesheet)
- submit(title: str, *, collection_id: str | None = None, discussion_type: str | None = None, draft_id: str | None = None, flair_id: str | None = None, flair_text: str | None = None, inline_media: Dict[str, praw.models.InlineMedia] | None = None, nsfw: bool = False, resubmit: bool = True, selftext: str | None = None, send_replies: bool = True, spoiler: bool = False, url: str | None = None) praw.models.Submission
Add a submission to the
Subreddit
.- Parameters:
title – The title of the submission.
collection_id – The UUID of a
Collection
to add the newly-submitted post to.discussion_type – Set to
"CHAT"
to enable live discussion instead of traditional comments (default:None
).draft_id – The ID of a draft to submit.
flair_id – The flair template to select (default:
None
).flair_text – If the template’s
flair_text_editable
value isTrue
, this value will set a custom text (default:None
).flair_id
is required whenflair_text
is provided.inline_media – A dict of
InlineMedia
objects where the key is the placeholder name inselftext
.nsfw – Whether the submission should be marked NSFW (default:
False
).resubmit – When
False
, an error will occur if the URL has already been submitted (default:True
).selftext – The Markdown formatted content for a
text
submission. Use an empty string,""
, to make a title-only submission.send_replies – When
True
, messages will be sent to the submission author when comments are made to the submission (default:True
).spoiler – Whether the submission should be marked as a spoiler (default:
False
).url – The URL for a
link
submission.
- Returns:
A
Submission
object for the newly created submission.
Either
selftext
orurl
can be provided, but not both.For example, to submit a URL to r/test do:
title = "PRAW documentation" url = "https://praw.readthedocs.io" reddit.subreddit("test").submit(title, url=url)
For example, to submit a self post with inline media do:
from praw.models import InlineGif, InlineImage, InlineVideo gif = InlineGif(path="path/to/image.gif", caption="optional caption") image = InlineImage(path="path/to/image.jpg", caption="optional caption") video = InlineVideo(path="path/to/video.mp4", caption="optional caption") selftext = "Text with a gif {gif1} an image {image1} and a video {video1} inline" media = {"gif1": gif, "image1": image, "video1": video} reddit.subreddit("test").submit("title", inline_media=media, selftext=selftext)
Note
Inserted media will have a padding of
\\n\\n
automatically added. This is due to the weirdness with Reddit’s API. Using the example above, the result selftext body will look like so:Text with a gif  an image  and video  inline
Note
To submit a post to a subreddit with the
"news"
flair, you can get the flair id like this:choices = list(subreddit.flair.link_templates.user_selectable()) template_id = next(x for x in choices if x["flair_text"] == "news")["flair_template_id"] subreddit.submit("title", flair_id=template_id, url="https://www.news.com/")
See also
submit_gallery()
to submit more than one image in the same postsubmit_image()
to submit imagessubmit_poll()
to submit pollssubmit_video()
to submit videos and videogifs
- submit_gallery(title: str, images: List[Dict[str, str]], *, collection_id: str | None = None, discussion_type: str | None = None, flair_id: str | None = None, flair_text: str | None = None, nsfw: bool = False, send_replies: bool = True, spoiler: bool = False)
Add an image gallery submission to the subreddit.
- Parameters:
title – The title of the submission.
images – The images to post in dict with the following structure:
{"image_path": "path", "caption": "caption", "outbound_url": "url"}
, onlyimage_path
is required.collection_id – The UUID of a
Collection
to add the newly-submitted post to.discussion_type – Set to
"CHAT"
to enable live discussion instead of traditional comments (default:None
).flair_id – The flair template to select (default:
None
).flair_text – If the template’s
flair_text_editable
value isTrue
, this value will set a custom text (default:None
).flair_id
is required whenflair_text
is provided.nsfw – Whether the submission should be marked NSFW (default:
False
).send_replies – When
True
, messages will be sent to the submission author when comments are made to the submission (default:True
).spoiler – Whether the submission should be marked asa spoiler (default:
False
).
- Returns:
A
Submission
object for the newly created submission.- Raises:
ClientException
ifimage_path
inimages
refers to a file that is not an image.
For example, to submit an image gallery to r/test do:
title = "My favorite pictures" image = "/path/to/image.png" image2 = "/path/to/image2.png" image3 = "/path/to/image3.png" images = [ {"image_path": image}, { "image_path": image2, "caption": "Image caption 2", }, { "image_path": image3, "caption": "Image caption 3", "outbound_url": "https://example.com/link3", }, ] reddit.subreddit("test").submit_gallery(title, images)
See also
submit()
to submit url posts and selftextssubmit_image()
to submit single imagessubmit_poll()
to submit pollssubmit_video()
to submit videos and videogifs
- submit_image(title: str, image_path: str, *, collection_id: str | None = None, discussion_type: str | None = None, flair_id: str | None = None, flair_text: str | None = None, nsfw: bool = False, resubmit: bool = True, send_replies: bool = True, spoiler: bool = False, timeout: int = 10, without_websockets: bool = False)
Add an image submission to the subreddit.
- Parameters:
collection_id – The UUID of a
Collection
to add the newly-submitted post to.discussion_type – Set to
"CHAT"
to enable live discussion instead of traditional comments (default:None
).flair_id – The flair template to select (default:
None
).flair_text – If the template’s
flair_text_editable
value isTrue
, this value will set a custom text (default:None
).flair_id
is required whenflair_text
is provided.image_path – The path to an image, to upload and post.
nsfw – Whether the submission should be marked NSFW (default:
False
).resubmit – When
False
, an error will occur if the URL has already been submitted (default:True
).send_replies – When
True
, messages will be sent to the submission author when comments are made to the submission (default:True
).spoiler – Whether the submission should be marked as a spoiler (default:
False
).timeout – Specifies a particular timeout, in seconds. Use to avoid “Websocket error” exceptions (default:
10
).title – The title of the submission.
without_websockets – Set to
True
to disable use of WebSockets (see note below for an explanation). IfTrue
, this method doesn’t return anything (default:False
).
- Returns:
A
Submission
object for the newly created submission, unlesswithout_websockets
isTrue
.- Raises:
ClientException
ifimage_path
refers to a file that is not an image.
Note
Reddit’s API uses WebSockets to respond with the link of the newly created post. If this fails, the method will raise
WebSocketException
. Occasionally, the Reddit post will still be created. More often, there is an error with the image file. If you frequently get exceptions but successfully created posts, try setting thetimeout
parameter to a value above 10.To disable the use of WebSockets, set
without_websockets=True
. This will make the method returnNone
, though the post will still be created. You may wish to do this if you are running your program in a restricted network environment, or using a proxy that doesn’t support WebSockets connections.For example, to submit an image to r/test do:
title = "My favorite picture" image = "/path/to/image.png" reddit.subreddit("test").submit_image(title, image)
See also
submit()
to submit url posts and selftextssubmit_gallery()
to submit more than one image in the same postsubmit_poll()
to submit pollssubmit_video()
to submit videos and videogifs
- submit_poll(title: str, *, collection_id: str | None = None, discussion_type: str | None = None, duration: int, flair_id: str | None = None, flair_text: str | None = None, nsfw: bool = False, options: List[str], resubmit: bool = True, selftext: str, send_replies: bool = True, spoiler: bool = False)
Add a poll submission to the subreddit.
- Parameters:
title – The title of the submission.
collection_id – The UUID of a
Collection
to add the newly-submitted post to.discussion_type – Set to
"CHAT"
to enable live discussion instead of traditional comments (default:None
).duration – The number of days the poll should accept votes, as an
int
. Valid values are between1
and7
, inclusive.flair_id – The flair template to select (default:
None
).flair_text – If the template’s
flair_text_editable
value isTrue
, this value will set a custom text (default:None
).flair_id
is required whenflair_text
is provided.nsfw – Whether the submission should be marked NSFW (default:
False
).options – A list of two to six poll options as
str
.resubmit – When
False
, an error will occur if the URL has already been submitted (default:True
).selftext – The Markdown formatted content for the submission. Use an empty string,
""
, to make a submission with no text contents.send_replies – When
True
, messages will be sent to the submission author when comments are made to the submission (default:True
).spoiler – Whether the submission should be marked as a spoiler (default:
False
).
- Returns:
A
Submission
object for the newly created submission.
For example, to submit a poll to r/test do:
title = "Do you like PRAW?" reddit.subreddit("test").submit_poll( title, selftext="", options=["Yes", "No"], duration=3 )
See also
submit()
to submit url posts and selftextssubmit_gallery()
to submit more than one image in the same postsubmit_image()
to submit single imagessubmit_video()
to submit videos and videogifs
- submit_video(title: str, video_path: str, *, collection_id: str | None = None, discussion_type: str | None = None, flair_id: str | None = None, flair_text: str | None = None, nsfw: bool = False, resubmit: bool = True, send_replies: bool = True, spoiler: bool = False, thumbnail_path: str | None = None, timeout: int = 10, videogif: bool = False, without_websockets: bool = False)
Add a video or videogif submission to the subreddit.
- Parameters:
title – The title of the submission.
video_path – The path to a video, to upload and post.
collection_id – The UUID of a
Collection
to add the newly-submitted post to.discussion_type – Set to
"CHAT"
to enable live discussion instead of traditional comments (default:None
).flair_id – The flair template to select (default:
None
).flair_text – If the template’s
flair_text_editable
value isTrue
, this value will set a custom text (default:None
).flair_id
is required whenflair_text
is provided.nsfw – Whether the submission should be marked NSFW (default:
False
).resubmit – When
False
, an error will occur if the URL has already been submitted (default:True
).send_replies – When
True
, messages will be sent to the submission author when comments are made to the submission (default:True
).spoiler – Whether the submission should be marked as a spoiler (default:
False
).thumbnail_path – The path to an image, to be uploaded and used as the thumbnail for this video. If not provided, the PRAW logo will be used as the thumbnail.
timeout – Specifies a particular timeout, in seconds. Use to avoid “Websocket error” exceptions (default:
10
).videogif – If
True
, the video is uploaded as a videogif, which is essentially a silent video (default:False
).without_websockets – Set to
True
to disable use of WebSockets (see note below for an explanation). IfTrue
, this method doesn’t return anything (default:False
).
- Returns:
A
Submission
object for the newly created submission, unlesswithout_websockets
isTrue
.- Raises:
ClientException
ifvideo_path
refers to a file that is not a video.
Note
Reddit’s API uses WebSockets to respond with the link of the newly created post. If this fails, the method will raise
WebSocketException
. Occasionally, the Reddit post will still be created. More often, there is an error with the image file. If you frequently get exceptions but successfully created posts, try setting thetimeout
parameter to a value above 10.To disable the use of WebSockets, set
without_websockets=True
. This will make the method returnNone
, though the post will still be created. You may wish to do this if you are running your program in a restricted network environment, or using a proxy that doesn’t support WebSockets connections.For example, to submit a video to r/test do:
title = "My favorite movie" video = "/path/to/video.mp4" reddit.subreddit("test").submit_video(title, video)
See also
submit()
to submit url posts and selftextssubmit_image()
to submit imagessubmit_gallery()
to submit more than one image in the same postsubmit_poll()
to submit polls
- subscribe(*, other_subreddits: List[praw.models.Subreddit] | None = None)
Subscribe to the subreddit.
- Parameters:
other_subreddits – When provided, also subscribe to the provided list of subreddits.
For example, to subscribe to r/test:
reddit.subreddit("test").subscribe()
- top(*, time_filter: str = 'all', **generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for top items.- Parameters:
time_filter – Can be one of:
"all"
,"day"
,"hour"
,"month"
,"week"
, or"year"
(default:"all"
).- Raises:
ValueError
iftime_filter
is invalid.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").top(time_filter="week") reddit.multireddit(redditor="samuraisam", name="programming").top(time_filter="day") reddit.redditor("spez").top(time_filter="month") reddit.redditor("spez").comments.top(time_filter="year") reddit.redditor("spez").submissions.top(time_filter="all") reddit.subreddit("all").top(time_filter="hour")
- traffic() Dict[str, List[List[int]]]
Return a dictionary of the
Subreddit
’s traffic statistics.- Raises:
prawcore.NotFound
when the traffic stats aren’t available to the authenticated user, that is, they are not public and the authenticated user is not a moderator of the subreddit.
The traffic method returns a dict with three keys. The keys are
day
,hour
andmonth
. Each key contains a list of lists with 3 or 4 values. The first value is a timestamp indicating the start of the category (start of the day for theday
key, start of the hour for thehour
key, etc.). The second, third, and fourth values indicate the unique pageviews, total pageviews, and subscribers, respectively.Note
The
hour
key does not contain subscribers, and therefore each sub-list contains three values.For example, to get the traffic stats for r/test:
stats = reddit.subreddit("test").traffic()
- unsubscribe(*, other_subreddits: List[praw.models.Subreddit] | None = None)
Unsubscribe from the subreddit.
- Parameters:
other_subreddits – When provided, also unsubscribe from the provided list of subreddits.
To unsubscribe from r/test:
reddit.subreddit("test").unsubscribe()
- widgets() praw.models.SubredditWidgets
Provide an instance of
SubredditWidgets
.Example usage
Get all sidebar widgets:
for widget in reddit.subreddit("test").widgets.sidebar: print(widget)
Get ID card widget:
print(reddit.subreddit("test").widgets.id_card)
- wiki() praw.models.reddit.subreddit.SubredditWiki
Provide an instance of
SubredditWiki
.This attribute can be used to discover all wikipages for a subreddit:
for wikipage in reddit.subreddit("test").wiki: print(wikipage)
To fetch the content for a given wikipage try:
wikipage = reddit.subreddit("test").wiki["proof"] print(wikipage.content_md)
WikiPage
- class praw.models.reddit.wikipage.WikiPage(reddit: praw.Reddit, subreddit: praw.models.Subreddit, name: str, revision: str | None = None, _data: Dict[str, Any] | None = None)
An individual
WikiPage
object.Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
content_html
The contents of the wiki page, as HTML.
content_md
The contents of the wiki page, as Markdown.
may_revise
A
bool
representing whether or not the authenticated user may edit the wiki page.name
The name of the wiki page.
revision_by
The
Redditor
who authored this revision of the wiki page.revision_date
The time of this revision, in Unix Time.
subreddit
The
Subreddit
this wiki page belongs to.- __init__(reddit: praw.Reddit, subreddit: praw.models.Subreddit, name: str, revision: str | None = None, _data: Dict[str, Any] | None = None)
Initialize a
WikiPage
instance.- Parameters:
revision – A specific revision ID to fetch. By default, fetches the most recent revision.
- discussions(**generator_kwargs: Any) Iterator[praw.models.Submission]
Return a
ListingGenerator
for discussions of a wiki page.Discussions are site-wide links to a wiki page.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.To view the titles of discussions of the page
"praw_test"
in r/test, try:for submission in reddit.subreddit("test").wiki["praw_test"].discussions(): print(submission.title)
- edit(*, content: str, reason: str | None = None, **other_settings: Any)
Edit this wiki page’s contents.
- Parameters:
content – The updated Markdown content of the page.
reason – The reason for the revision.
other_settings – Additional keyword arguments to pass.
For example, to replace the first wiki page of r/test with the phrase
"test wiki page"
:page = next(iter(reddit.subreddit("test").wiki)) page.edit(content="test wiki page")
- mod() WikiPageModeration
Provide an instance of
WikiPageModeration
.For example, to add u/spez as an editor on the wikipage
"praw_test"
try:reddit.subreddit("test").wiki["praw_test"].mod.add("spez")
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit) Any
Return an instance of
cls
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.
- revision(revision: str)
Return a specific version of this page by revision ID.
To view revision
"1234abc"
of"praw_test"
in r/test:page = reddit.subreddit("test").wiki["praw_test"].revision("1234abc")
- revisions(**generator_kwargs: str | int | Dict[str, str]) Generator[WikiPage, None, None]
Return a
ListingGenerator
for page revisions.Additional keyword arguments are passed in the initialization of
ListingGenerator
.To view the wiki revisions for
"praw_test"
in r/test try:for item in reddit.subreddit("test").wiki["praw_test"].revisions(): print(item)
To get
WikiPage
objects for each revision:for item in reddit.subreddit("test").wiki["praw_test"].revisions(): print(item["page"])
Exceptions in PRAW
In addition to exceptions under the praw.exceptions
namespace shown below,
exceptions might be raised that inherit from prawcore.PrawcoreException
. Please see
the following resource for information on those exceptions:
https://github.com/praw-dev/prawcore/blob/master/prawcore/exceptions.py
praw.exceptions
PRAW exception classes.
Includes two main exceptions: RedditAPIException
for when something goes wrong
on the server side, and ClientException
when something goes wrong on the
client side. Both of these classes extend PRAWException
.
All other exceptions are subclassed from ClientException
.
- exception praw.exceptions.APIException(items: List[RedditErrorItem | List[str] | str] | str, *optional_args: str)
Old class preserved for alias purposes.
Deprecated since version 7.0: Class
APIException
has been deprecated in favor ofRedditAPIException
. This class will be removed in PRAW 8.0.- __init__(items: List[RedditErrorItem | List[str] | str] | str, *optional_args: str)
Initialize a
RedditAPIException
instance.- Parameters:
items – Either a list of instances of
RedditErrorItem
or a list containing lists of unformed errors.optional_args – Takes the second and third arguments that
APIException
used to take.
- property error_type: str
Get error_type.
Deprecated since version 7.0: Accessing attributes through instances of
RedditAPIException
is deprecated. This behavior will be removed in PRAW 8.0. Check out the PRAW 7 Migration tutorial on how to migrate code from this behavior.
- property field: str
Get field.
Deprecated since version 7.0: Accessing attributes through instances of
RedditAPIException
is deprecated. This behavior will be removed in PRAW 8.0. Check out the PRAW 7 Migration tutorial on how to migrate code from this behavior.
- property message: str
Get message.
Deprecated since version 7.0: Accessing attributes through instances of
RedditAPIException
is deprecated. This behavior will be removed in PRAW 8.0. Check out the PRAW 7 Migration tutorial on how to migrate code from this behavior.
- static parse_exception_list(exceptions: List[RedditErrorItem | List[str]])
Covert an exception list into a
RedditErrorItem
list.
- with_traceback()
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- exception praw.exceptions.ClientException
Indicate exceptions that don’t involve interaction with Reddit’s API.
- __init__(*args, **kwargs)
- with_traceback()
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- exception praw.exceptions.DuplicateReplaceException
Indicate exceptions that involve the replacement of
MoreComments
.- __init__()
Initialize a
DuplicateReplaceException
instance.
- with_traceback()
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- exception praw.exceptions.InvalidFlairTemplateID(template_id: str)
Indicate exceptions where an invalid flair template ID is given.
- __init__(template_id: str)
Initialize an
InvalidFlairTemplateID
instance.
- with_traceback()
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- exception praw.exceptions.InvalidImplicitAuth
Indicate exceptions where an implicit auth type is used incorrectly.
- __init__()
Initialize an
InvalidImplicitAuth
instance.
- with_traceback()
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- exception praw.exceptions.InvalidURL(url: str, *, message: str = 'Invalid URL: {}')
Indicate exceptions where an invalid URL is entered.
- __init__(url: str, *, message: str = 'Invalid URL: {}')
Initialize an
InvalidURL
instance.- Parameters:
url – The invalid URL.
message – The message to display. Must contain a format identifier (
{}
or{0}
) (default:"Invalid URL: {}"
).
- with_traceback()
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- exception praw.exceptions.MediaPostFailed
Indicate exceptions where media uploads failed..
- __init__()
Initialize a
MediaPostFailed
instance.
- with_traceback()
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- exception praw.exceptions.MissingRequiredAttributeException
Indicate exceptions caused by not including a required attribute.
- __init__(*args, **kwargs)
- with_traceback()
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- exception praw.exceptions.PRAWException
The base PRAW Exception that all other exception classes extend.
- __init__(*args, **kwargs)
- with_traceback()
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- exception praw.exceptions.ReadOnlyException
Raised when a method call requires
read_only
mode to be disabled.- __init__(*args, **kwargs)
- with_traceback()
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- exception praw.exceptions.RedditAPIException(items: List[RedditErrorItem | List[str] | str] | str, *optional_args: str)
Container for error messages from Reddit’s API.
- __init__(items: List[RedditErrorItem | List[str] | str] | str, *optional_args: str)
Initialize a
RedditAPIException
instance.- Parameters:
items – Either a list of instances of
RedditErrorItem
or a list containing lists of unformed errors.optional_args – Takes the second and third arguments that
APIException
used to take.
- property error_type: str
Get error_type.
Deprecated since version 7.0: Accessing attributes through instances of
RedditAPIException
is deprecated. This behavior will be removed in PRAW 8.0. Check out the PRAW 7 Migration tutorial on how to migrate code from this behavior.
- property field: str
Get field.
Deprecated since version 7.0: Accessing attributes through instances of
RedditAPIException
is deprecated. This behavior will be removed in PRAW 8.0. Check out the PRAW 7 Migration tutorial on how to migrate code from this behavior.
- property message: str
Get message.
Deprecated since version 7.0: Accessing attributes through instances of
RedditAPIException
is deprecated. This behavior will be removed in PRAW 8.0. Check out the PRAW 7 Migration tutorial on how to migrate code from this behavior.
- static parse_exception_list(exceptions: List[RedditErrorItem | List[str]])
Covert an exception list into a
RedditErrorItem
list.
- with_traceback()
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- class praw.exceptions.RedditErrorItem(error_type: str, *, field: str | None = None, message: str | None = None)
Represents a single error returned from Reddit’s API.
- exception praw.exceptions.TooLargeMediaException(*, actual: int, maximum_size: int)
Indicate exceptions from uploading media that’s too large.
- __init__(*, actual: int, maximum_size: int)
Initialize a
TooLargeMediaException
instance.- Parameters:
actual – The actual size of the uploaded media.
maximum_size – The maximum size of the uploaded media.
- with_traceback()
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- exception praw.exceptions.WebSocketException(message: str, exception: Exception | None)
Indicate exceptions caused by use of WebSockets.
- __init__(message: str, exception: Exception | None)
Initialize a
WebSocketException
instance.- Parameters:
message – The exception message.
exception –
The exception thrown by the websocket library.
Note
This parameter is deprecated. It will be removed in PRAW 8.0.
- with_traceback()
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
Other Classes
The following list of classes are provided here for complete documentation. You should not likely need to work with these classes directly, but rather through instances of them bound to an attribute of one of the PRAW models.
Collection
- class praw.models.Collection(reddit: praw.Reddit, _data: Dict[str, Any] = None, collection_id: str | None = None, permalink: str | None = None)
Class to represent a
Collection
.Obtain an instance via:
collection = reddit.subreddit("test").collections("some_uuid")
or
collection = reddit.subreddit("test").collections( permalink="https://reddit.com/r/SUBREDDIT/collection/some_uuid" )
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
author
The
Redditor
who created the collection.collection_id
The UUID of the collection.
created_at_utc
Time the collection was created, represented in Unix Time.
description
The collection description.
display_layout
The collection display layout.
last_update_utc
Time the collection was last updated, represented in Unix Time.
link_ids
A list of
Submission
fullnames.permalink
The collection’s permalink (to view on the web).
sorted_links
An iterable listing of the posts in this collection.
title
The title of the collection.
- __init__(reddit: praw.Reddit, _data: Dict[str, Any] = None, collection_id: str | None = None, permalink: str | None = None)
Initialize a
Collection
instance.- Parameters:
reddit – An instance of
Reddit
._data – Any data associated with the
Collection
.collection_id – The ID of the
Collection
.permalink – The permalink of the
Collection
.
- __iter__() Generator[Any, None, None]
Provide a way to iterate over the posts in this
Collection
.Example usage:
collection = reddit.subreddit("test").collections("some_uuid") for submission in collection: print(submission.title, submission.permalink)
- __len__() int
Get the number of posts in this
Collection
.Example usage:
collection = reddit.subreddit("test").collections("some_uuid") print(len(collection))
- follow()
Follow this
Collection
.Example usage:
reddit.subreddit("test").collections("some_uuid").follow()
See also
- mod() CollectionModeration
Get an instance of
CollectionModeration
.Provides access to various methods, including
add_post()
,delete()
,reorder()
, andupdate_title()
.Example usage:
collection = reddit.subreddit("test").collections("some_uuid") collection.mod.update_title("My new title!")
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit) Any
Return an instance of
cls
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.
- subreddit() praw.models.Subreddit
Get the subreddit that this collection belongs to.
For example:
collection = reddit.subreddit("test").collections("some_uuid") subreddit = collection.subreddit
- unfollow()
Unfollow this
Collection
.Example usage:
reddit.subreddit("test").collections("some_uuid").unfollow()
See also
CollectionModeration
- class praw.models.reddit.collections.CollectionModeration(reddit: praw.Reddit, collection_id: str)
Class to support moderation actions on a
Collection
.Obtain an instance via:
reddit.subreddit("test").collections("some_uuid").mod
- __init__(reddit: praw.Reddit, collection_id: str)
Initialize a
CollectionModeration
instance.- Parameters:
collection_id – The ID of a
Collection
.
- add_post(submission: praw.models.Submission)
Add a post to the collection.
- Parameters:
submission – The post to add, a
Submission
, its permalink as astr
, its fullname as astr
, or its ID as astr
.
Example usage:
collection = reddit.subreddit("test").collections("some_uuid") collection.mod.add_post("bgibu9")
See also
- delete()
Delete this collection.
Example usage:
reddit.subreddit("test").collections("some_uuid").mod.delete()
See also
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit) Any
Return an instance of
cls
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.
- remove_post(submission: praw.models.Submission)
Remove a post from the collection.
- Parameters:
submission – The post to remove, a
Submission
, its permalink as astr
, its fullname as astr
, or its ID as astr
.
Example usage:
collection = reddit.subreddit("test").collections("some_uuid") collection.mod.remove_post("bgibu9")
See also
- reorder(links: List[str | praw.models.Submission])
Reorder posts in the collection.
- Parameters:
links – A list of
Submission
s or astr
that is either a fullname or an ID.
Example usage:
collection = reddit.subreddit("test").collections("some_uuid") current_order = collection.link_ids new_order = reversed(current_order) collection.mod.reorder(new_order)
- update_description(description: str)
Update the collection’s description.
- Parameters:
description – The new description.
Example usage:
collection = reddit.subreddit("test").collections("some_uuid") collection.mod.update_description("Please enjoy these links!")
See also
- update_display_layout(display_layout: str)
Update the collection’s display layout.
- Parameters:
display_layout – Either
"TIMELINE"
for events or discussions or"GALLERY"
for images or memes. PassingNone
will clear the set layout andcollection.display_layout
will beNone
, however, the collection will appear on Reddit as ifdisplay_layout
is set to"TIMELINE"
.
Example usage:
collection = reddit.subreddit("test").collections("some_uuid") collection.mod.update_display_layout("GALLERY")
SubredditCollections
- class praw.models.reddit.collections.SubredditCollections(reddit: praw.Reddit, subreddit: praw.models.Subreddit, _data: Dict[str, Any] | None = None)
Class to represent a
Subreddit
’sCollection
s.Obtain an instance via:
reddit.subreddit("test").collections
- __call__(collection_id: str | None = None, permalink: str | None = None)
Return the
Collection
with the specified ID.- Parameters:
collection_id – The ID of a
Collection
(default:None
).permalink – The permalink of a collection (default:
None
).
- Returns:
The specified
Collection
.
Exactly one of
collection_id
orpermalink
is required.Example usage:
subreddit = reddit.subreddit("test") uuid = "847e4548-a3b5-4ad7-afb4-edbfc2ed0a6b" collection = subreddit.collections(uuid) print(collection.title) print(collection.description) permalink = "https://www.reddit.com/r/SUBREDDIT/collection/" + uuid collection = subreddit.collections(permalink=permalink) print(collection.title) print(collection.description)
- __init__(reddit: praw.Reddit, subreddit: praw.models.Subreddit, _data: Dict[str, Any] | None = None)
Initialize a
SubredditCollections
instance.
- __iter__()
Iterate over the
Subreddit
’sCollection
s.Example usage:
for collection in reddit.subreddit("test").collections: print(collection.permalink)
- mod() SubredditCollectionsModeration
Get an instance of
SubredditCollectionsModeration
.Provides
create()
:my_sub = reddit.subreddit("test") new_collection = my_sub.collections.mod.create(title="Title", description="desc")
SubredditCollectionsModeration
- class praw.models.reddit.collections.SubredditCollectionsModeration(reddit: praw.Reddit, sub_fullname: str, _data: Dict[str, Any] | None = None)
Class to represent moderator actions on a
Subreddit
’sCollection
s.Obtain an instance via:
reddit.subreddit("test").collections.mod
- __init__(reddit: praw.Reddit, sub_fullname: str, _data: Dict[str, Any] | None = None)
Initialize a
SubredditCollectionsModeration
instance.
- create(*, description: str, display_layout: str | None = None, title: str)
Create a new
Collection
.The authenticated account must have appropriate moderator permissions in the subreddit this collection belongs to.
- Parameters:
description – The description, up to 500 characters.
display_layout – Either
"TIMELINE"
for events or discussions or"GALLERY"
for images or memes. Passing""
orNone
will make the collection appear on Reddit as if this is set to"TIMELINE"
(default:None
).title – The title of the collection, up to 300 characters.
- Returns:
The newly created
Collection
.
Example usage:
my_sub = reddit.subreddit("test") new_collection = my_sub.collections.mod.create(title="Title", description="desc") new_collection.mod.add_post("bgibu9")
To specify the display layout as
"GALLERY"
when creating the collection:my_sub = reddit.subreddit("test") new_collection = my_sub.collections.mod.create( title="Title", description="desc", display_layout="GALLERY" ) new_collection.mod.add_post("bgibu9")
See also
SubmissionFlair
- class praw.models.reddit.submission.SubmissionFlair(submission: praw.models.Submission)
Provide a set of functions pertaining to
Submission
flair.- __init__(submission: praw.models.Submission)
Initialize a
SubmissionFlair
instance.- Parameters:
submission – The
Submission
associated with the flair functions.
- choices() List[Dict[str, bool | list | str]]
Return list of available flair choices.
Choices are required in order to use
select()
.For example:
choices = submission.flair.choices()
- select(flair_template_id: str, *, text: str | None = None)
Select flair for submission.
- Parameters:
flair_template_id – The flair template to select. The possible values can be discovered through
choices()
.text – If the template’s
flair_text_editable
value isTrue
, this value will set a custom text (default:None
).
For example, to select an arbitrary editable flair text (assuming there is one) and set a custom value try:
choices = submission.flair.choices() template_id = next(x for x in choices if x["flair_text_editable"])["flair_template_id"] submission.flair.select(template_id, text="my custom value")
SubredditFlair
- class praw.models.reddit.subreddit.SubredditFlair(subreddit: praw.models.Subreddit)
Provide a set of functions to interact with a
Subreddit
’s flair.- __call__(redditor: praw.models.Redditor | str | None = None, **generator_kwargs: Any) Iterator[praw.models.Redditor]
Return a
ListingGenerator
for Redditors and their flairs.- Parameters:
redditor – When provided, yield at most a single
Redditor
instance (default:None
).
Additional keyword arguments are passed in the initialization of
ListingGenerator
.Usage:
for flair in reddit.subreddit("test").flair(limit=None): print(flair)
- __init__(subreddit: praw.models.Subreddit)
Initialize a
SubredditFlair
instance.- Parameters:
subreddit – The subreddit whose flair to work with.
- configure(*, link_position: str = 'left', link_self_assign: bool = False, position: str = 'right', self_assign: bool = False, **settings: Any)
Update the
Subreddit
’s flair configuration.- Parameters:
link_position – One of
"left"
,"right"
, orFalse
to disable (default:"left"
).link_self_assign – Permit self assignment of link flair (default:
False
).position – One of
"left"
,"right"
, orFalse
to disable (default:"right"
).self_assign – Permit self assignment of user flair (default:
False
).
subreddit = reddit.subreddit("test") subreddit.flair.configure(link_position="right", self_assign=True)
Additional keyword arguments can be provided to handle new settings as Reddit introduces them.
- delete(redditor: praw.models.Redditor | str)
Delete flair for a
Redditor
.- Parameters:
redditor – A redditor name or
Redditor
instance.
See also
update()
to delete the flair of many redditors at once.
- delete_all() List[Dict[str, str | bool | Dict[str, str]]]
Delete all
Redditor
flair in theSubreddit
.- Returns:
List of dictionaries indicating the success or failure of each delete.
- link_templates() praw.models.reddit.subreddit.SubredditLinkFlairTemplates
Provide an instance of
SubredditLinkFlairTemplates
.Use this attribute for interacting with a
Subreddit
’s link flair templates. For example to list all the link flair templates for a subreddit which you have theflair
moderator permission on try:for template in reddit.subreddit("test").flair.link_templates: print(template)
- set(redditor: praw.models.Redditor | str, *, css_class: str = '', flair_template_id: str | None = None, text: str = '')
Set flair for a
Redditor
.- Parameters:
redditor – A redditor name or
Redditor
instance.text – The flair text to associate with the
Redditor
orSubmission
(default:""
).css_class – The css class to associate with the flair html (default:
""
). Use either this orflair_template_id
.flair_template_id – The ID of the flair template to be used (default:
None
). Use either this orcss_class
.
This method can only be used by an authenticated user who is a moderator of the associated
Subreddit
.For example:
reddit.subreddit("test").flair.set("bboe", text="PRAW author", css_class="mods") template = "6bd28436-1aa7-11e9-9902-0e05ab0fad46" reddit.subreddit("test").flair.set( "spez", text="Reddit CEO", flair_template_id=template )
- templates() praw.models.reddit.subreddit.SubredditRedditorFlairTemplates
Provide an instance of
SubredditRedditorFlairTemplates
.Use this attribute for interacting with a
Subreddit
’s flair templates. For example to list all the flair templates for a subreddit which you have theflair
moderator permission on try:for template in reddit.subreddit("test").flair.templates: print(template)
- update(flair_list: Iterator[str | praw.models.Redditor | Dict[str, str | praw.models.Redditor]], *, text: str = '', css_class: str = '') List[Dict[str, str | bool | Dict[str, str]]]
Set or clear the flair for many redditors at once.
- Parameters:
flair_list –
Each item in this list should be either:
The name of a redditor.
An instance of
Redditor
.A dictionary mapping keys
"user"
,"flair_text"
, and"flair_css_class"
to their respective values. The"user"
key should map to a redditor, as described above. When a dictionary isn’t provided, or the dictionary is missing either"flair_text"
or"flair_css_class"
keys, the default values will come from the other arguments.
css_class – The css class to use when not explicitly provided in
flair_list
(default:""
).text – The flair text to use when not explicitly provided in
flair_list
(default:""
).
- Returns:
List of dictionaries indicating the success or failure of each update.
For example, to clear the flair text, and set the
"praw"
flair css class on a few users try:subreddit.flair.update(["bboe", "spez", "spladug"], css_class="praw")
SubredditFlairTemplates
- class praw.models.reddit.subreddit.SubredditFlairTemplates(subreddit: praw.models.Subreddit)
Provide functions to interact with a
Subreddit
’s flair templates.- __init__(subreddit: praw.models.Subreddit)
Initialize a
SubredditFlairTemplates
instance.- Parameters:
subreddit – The subreddit whose flair templates to work with.
Note
This class should not be initialized directly. Instead, obtain an instance via:
reddit.subreddit("test").flair.templates
orreddit.subreddit("test").flair.link_templates
.
- __iter__()
Abstract method to return flair templates.
- delete(template_id: str)
Remove a flair template provided by
template_id
.For example, to delete the first
Redditor
flair template listed, try:template_info = list(subreddit.flair.templates)[0] subreddit.flair.templates.delete(template_info["id"])
- static flair_type(is_link: bool) str
Return
"LINK_FLAIR"
or"USER_FLAIR"
depending onis_link
value.
- update(template_id: str, *, allowable_content: str | None = None, background_color: str | None = None, css_class: str | None = None, fetch: bool = True, max_emojis: int | None = None, mod_only: bool | None = None, text: str | None = None, text_color: str | None = None, text_editable: bool | None = None)
Update the flair template provided by
template_id
.- Parameters:
template_id – The flair template to update. If not valid then an exception will be thrown.
allowable_content – If specified, most be one of
"all"
,"emoji"
, or"text"
to restrict content to that type. If set to"emoji"
then the"text"
param must be a valid emoji string, for example,":snoo:"
.background_color – The flair template’s new background color, as a hex color.
css_class – The flair template’s new css_class (default:
""
).fetch – Whether PRAW will fetch existing information on the existing flair before updating (default:
True
).max_emojis – Maximum emojis in the flair (Reddit defaults this value to
10
).mod_only – Indicate if the flair can only be used by moderators.
text – The flair template’s new text.
text_color – The flair template’s new text color, either
"light"
or"dark"
.text_editable – Indicate if the flair text can be modified for each redditor that sets it (default:
False
).
Warning
If parameter
fetch
is set toFalse
, all parameters not provided will be reset to their default (None
orFalse
) values.For example, to make a user flair template text editable, try:
template_info = list(subreddit.flair.templates)[0] subreddit.flair.templates.update( template_info["id"], text=template_info["flair_text"], text_editable=True, )
SubredditLinkFlairTemplates
- class praw.models.reddit.subreddit.SubredditLinkFlairTemplates(subreddit: praw.models.Subreddit)
Provide functions to interact with link flair templates.
- __init__(subreddit: praw.models.Subreddit)
Initialize a
SubredditFlairTemplates
instance.- Parameters:
subreddit – The subreddit whose flair templates to work with.
Note
This class should not be initialized directly. Instead, obtain an instance via:
reddit.subreddit("test").flair.templates
orreddit.subreddit("test").flair.link_templates
.
- __iter__() Generator[Dict[str, str | int | bool | List[Dict[str, str]]], None, None]
Iterate through the link flair templates as a moderator.
For example:
for template in reddit.subreddit("test").flair.link_templates: print(template)
- add(text: str, *, allowable_content: str | None = None, background_color: str | None = None, css_class: str = '', max_emojis: int | None = None, mod_only: bool | None = None, text_color: str | None = None, text_editable: bool = False)
Add a link flair template to the associated subreddit.
- Parameters:
text – The flair template’s text.
allowable_content – If specified, most be one of
"all"
,"emoji"
, or"text"
to restrict content to that type. If set to"emoji"
then the"text"
param must be a valid emoji string, for example,":snoo:"
.background_color – The flair template’s new background color, as a hex color.
css_class – The flair template’s css_class (default:
""
).max_emojis – Maximum emojis in the flair (Reddit defaults this value to
10
).mod_only – Indicate if the flair can only be used by moderators.
text_color – The flair template’s new text color, either
"light"
or"dark"
.text_editable – Indicate if the flair text can be modified for each redditor that sets it (default:
False
).
For example, to add an editable link flair try:
reddit.subreddit("test").flair.link_templates.add( "PRAW", css_class="praw", text_editable=True, )
- clear()
Remove all link flair templates from the subreddit.
For example:
reddit.subreddit("test").flair.link_templates.clear()
- delete(template_id: str)
Remove a flair template provided by
template_id
.For example, to delete the first
Redditor
flair template listed, try:template_info = list(subreddit.flair.templates)[0] subreddit.flair.templates.delete(template_info["id"])
- static flair_type(is_link: bool) str
Return
"LINK_FLAIR"
or"USER_FLAIR"
depending onis_link
value.
- update(template_id: str, *, allowable_content: str | None = None, background_color: str | None = None, css_class: str | None = None, fetch: bool = True, max_emojis: int | None = None, mod_only: bool | None = None, text: str | None = None, text_color: str | None = None, text_editable: bool | None = None)
Update the flair template provided by
template_id
.- Parameters:
template_id – The flair template to update. If not valid then an exception will be thrown.
allowable_content – If specified, most be one of
"all"
,"emoji"
, or"text"
to restrict content to that type. If set to"emoji"
then the"text"
param must be a valid emoji string, for example,":snoo:"
.background_color – The flair template’s new background color, as a hex color.
css_class – The flair template’s new css_class (default:
""
).fetch – Whether PRAW will fetch existing information on the existing flair before updating (default:
True
).max_emojis – Maximum emojis in the flair (Reddit defaults this value to
10
).mod_only – Indicate if the flair can only be used by moderators.
text – The flair template’s new text.
text_color – The flair template’s new text color, either
"light"
or"dark"
.text_editable – Indicate if the flair text can be modified for each redditor that sets it (default:
False
).
Warning
If parameter
fetch
is set toFalse
, all parameters not provided will be reset to their default (None
orFalse
) values.For example, to make a user flair template text editable, try:
template_info = list(subreddit.flair.templates)[0] subreddit.flair.templates.update( template_info["id"], text=template_info["flair_text"], text_editable=True, )
SubredditRedditorFlairTemplates
- class praw.models.reddit.subreddit.SubredditRedditorFlairTemplates(subreddit: praw.models.Subreddit)
Provide functions to interact with
Redditor
flair templates.- __init__(subreddit: praw.models.Subreddit)
Initialize a
SubredditFlairTemplates
instance.- Parameters:
subreddit – The subreddit whose flair templates to work with.
Note
This class should not be initialized directly. Instead, obtain an instance via:
reddit.subreddit("test").flair.templates
orreddit.subreddit("test").flair.link_templates
.
- __iter__() Generator[Dict[str, str | int | bool | List[Dict[str, str]]], None, None]
Iterate through the user flair templates.
For example:
for template in reddit.subreddit("test").flair.templates: print(template)
- add(text: str, *, allowable_content: str | None = None, background_color: str | None = None, css_class: str = '', max_emojis: int | None = None, mod_only: bool | None = None, text_color: str | None = None, text_editable: bool = False)
Add a redditor flair template to the associated subreddit.
- Parameters:
text – The flair template’s text.
allowable_content – If specified, most be one of
"all"
,"emoji"
, or"text"
to restrict content to that type. If set to"emoji"
then the"text"
param must be a valid emoji string, for example,":snoo:"
.background_color – The flair template’s new background color, as a hex color.
css_class – The flair template’s css_class (default:
""
).max_emojis – Maximum emojis in the flair (Reddit defaults this value to
10
).mod_only – Indicate if the flair can only be used by moderators.
text_color – The flair template’s new text color, either
"light"
or"dark"
.text_editable – Indicate if the flair text can be modified for each redditor that sets it (default:
False
).
For example, to add an editable redditor flair try:
reddit.subreddit("test").flair.templates.add( "PRAW", css_class="praw", text_editable=True, )
- clear()
Remove all
Redditor
flair templates from the subreddit.For example:
reddit.subreddit("test").flair.templates.clear()
- delete(template_id: str)
Remove a flair template provided by
template_id
.For example, to delete the first
Redditor
flair template listed, try:template_info = list(subreddit.flair.templates)[0] subreddit.flair.templates.delete(template_info["id"])
- static flair_type(is_link: bool) str
Return
"LINK_FLAIR"
or"USER_FLAIR"
depending onis_link
value.
- update(template_id: str, *, allowable_content: str | None = None, background_color: str | None = None, css_class: str | None = None, fetch: bool = True, max_emojis: int | None = None, mod_only: bool | None = None, text: str | None = None, text_color: str | None = None, text_editable: bool | None = None)
Update the flair template provided by
template_id
.- Parameters:
template_id – The flair template to update. If not valid then an exception will be thrown.
allowable_content – If specified, most be one of
"all"
,"emoji"
, or"text"
to restrict content to that type. If set to"emoji"
then the"text"
param must be a valid emoji string, for example,":snoo:"
.background_color – The flair template’s new background color, as a hex color.
css_class – The flair template’s new css_class (default:
""
).fetch – Whether PRAW will fetch existing information on the existing flair before updating (default:
True
).max_emojis – Maximum emojis in the flair (Reddit defaults this value to
10
).mod_only – Indicate if the flair can only be used by moderators.
text – The flair template’s new text.
text_color – The flair template’s new text color, either
"light"
or"dark"
.text_editable – Indicate if the flair text can be modified for each redditor that sets it (default:
False
).
Warning
If parameter
fetch
is set toFalse
, all parameters not provided will be reset to their default (None
orFalse
) values.For example, to make a user flair template text editable, try:
template_info = list(subreddit.flair.templates)[0] subreddit.flair.templates.update( template_info["id"], text=template_info["flair_text"], text_editable=True, )
InlineGif
InlineImage
- class praw.models.InlineImage(*, caption: str = None, path: str)
Class to provide am image to embed in text.
- __init__(*, caption: str = None, path: str)
Initialize an
InlineMedia
instance.- Parameters:
caption – An optional caption to add to the image (default:
None
).path – The path to a media file.
InlineMedia
- class praw.models.InlineMedia(*, caption: str = None, path: str)
Provides a way to embed media in self posts.
- __init__(*, caption: str = None, path: str)
Initialize an
InlineMedia
instance.- Parameters:
caption – An optional caption to add to the image (default:
None
).path – The path to a media file.
InlineVideo
- class praw.models.InlineVideo(*, caption: str = None, path: str)
Class to provide a video to embed in text.
- __init__(*, caption: str = None, path: str)
Initialize an
InlineMedia
instance.- Parameters:
caption – An optional caption to add to the image (default:
None
).path – The path to a media file.
BaseModNotes
- class praw.models.mod_notes.BaseModNotes(reddit: praw.Reddit)
Provides base methods to interact with moderator notes.
- __init__(reddit: praw.Reddit)
Initialize a
BaseModNotes
instance.- Parameters:
reddit – An instance of
Reddit
.
- create(*, label: str | None = None, note: str, redditor: Redditor | str | None = None, subreddit: praw.models.Subreddit | str | None = None, thing: Comment | Submission | str | None = None, **other_settings: Any) praw.models.ModNote
Create a
ModNote
for a redditor in the specified subreddit.- Parameters:
label – The label for the note. As of this writing, this can be one of the following:
"ABUSE_WARNING"
,"BAN"
,"BOT_BAN"
,"HELPFUL_USER"
,"PERMA_BAN"
,"SOLID_CONTRIBUTOR"
,"SPAM_WARNING"
,"SPAM_WATCH"
, orNone
(default:None
).note – The content of the note. As of this writing, this is limited to 250 characters.
redditor –
The redditor to create the note for (default:
None
).Note
This parameter is required if
thing
is not provided or this is not called from aRedditor
instance (e.g.,reddit.redditor.notes
).subreddit –
The subreddit associated with the note (default:
None
).Note
This parameter is required if
thing
is not provided or this is not called from aSubreddit
instance (e.g.,reddit.subreddit.mod
).thing – Either the fullname of a comment/submission, a
Comment
, or aSubmission
to associate with the note.other_settings – Additional keyword arguments can be provided to handle new parameters as Reddit introduces them.
- Returns:
The new
ModNote
object.
For example, to create a note for u/spez in r/test:
reddit.subreddit("test").mod.notes.create( label="HELPFUL_USER", note="Test note", redditor="spez" ) # or reddit.redditor("spez").mod.notes.create( label="HELPFUL_USER", note="Test note", subreddit="test" ) # or reddit.notes.create( label="HELPFUL_USER", note="Test note", redditor="spez", subreddit="test" )
- delete(*, delete_all: bool = False, note_id: str | None = None, redditor: Redditor | str | None = None, subreddit: praw.models.Subreddit | str | None = None)
Delete note(s) for a redditor.
- Parameters:
delete_all –
When
True
, delete all notes for the specified redditor in the specified subreddit (default:False
).Note
This will make a request for each note.
note_id – The ID of the note to delete. This parameter is ignored if
delete_all
isTrue
.redditor –
The redditor to delete the note(s) for (default:
None
). Can be aRedditor
instance or a redditor name.Note
This parameter is required if this method is not called from a
Redditor
instance (e.g.,redditor.notes
).subreddit –
The subreddit to delete the note(s) from (default:
None
). Can be aSubreddit
instance or a subreddit name.Note
This parameter is required if this method is not called from a
Subreddit
instance (e.g.,reddit.subreddit.mod
).
For example, to delete a note with the ID
"ModNote_d324b280-5ecc-435d-8159-3e259e84e339"
, try:reddit.subreddit("test").mod.notes.delete( note_id="ModNote_d324b280-5ecc-435d-8159-3e259e84e339", redditor="spez" ) # or reddit.redditor("spez").notes.delete( note_id="ModNote_d324b280-5ecc-435d-8159-3e259e84e339", subreddit="test" ) # or reddit.notes.delete( note_id="ModNote_d324b280-5ecc-435d-8159-3e259e84e339", subreddit="test", redditor="spez", )
To delete all notes for u/spez, try:
reddit.subreddit("test").mod.notes.delete(delete_all=True, redditor="spez") # or reddit.redditor("spez").notes.delete(delete_all=True, subreddit="test") # or reddit.notes.delete(delete_all=True, subreddit="test", redditor="spez")
ModNote
- class praw.models.ModNote(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Represent a moderator note.
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
action
If this note represents a moderator action, this field indicates the type of action. For example,
"banuser"
if the action was banning a user.created_at
Time the moderator note was created, represented in Unix Time.
description
If this note represents a moderator action, this field indicates the description of the action. For example, if the action was banning the user, this is the ban reason.
details
If this note represents a moderator action, this field indicates the details of the action. For example, if the action was banning the user, this is the duration of the ban.
id
The ID of the moderator note.
label
The label applied to the note, currently one of:
"ABUSE_WARNING"
,"BAN"
,"BOT_BAN"
,"HELPFUL_USER"
,"PERMA_BAN"
,"SOLID_CONTRIBUTOR"
,"SPAM_WARNING"
,"SPAM_WATCH"
, orNone
.moderator
The moderator who created the note.
note
The text of the note.
reddit_id
The fullname of the object this note is attributed to, or
None
if not set. If this note represents a moderators action, this is the fullname of the object the action was performed on.subreddit
The subreddit this note belongs to.
type
The type of note, currently one of:
"APPROVAL"
,"BAN"
,"CONTENT_CHANGE"
,"INVITE"
,"MUTE"
,"NOTE"
,"REMOVAL"
, or"SPAM"
.user
The redditor the note is for.
- __init__(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Initialize a
PRAWBase
instance.- Parameters:
reddit – An instance of
Reddit
.
- delete()
Delete this note.
For example, to delete the last note for u/spez from r/test, try:
for note in reddit.subreddit("test").mod.notes("spez"): note.delete()
ModNoteMixin
- class praw.models.reddit.mixins.ModNoteMixin
Interface for classes that can have a moderator note set on them.
- author_notes(**generator_kwargs) Generator[praw.models.ModNote, None, None]
Get the moderator notes for the author of this object in the subreddit it’s posted in.
- Parameters:
generator_kwargs – Additional keyword arguments are passed in the initialization of the moderator note generator.
- Returns:
A generator of
ModNote
.
For example, to list all notes the author of a submission, try:
for note in reddit.submission("92dd8").mod.author_notes(): print(f"{note.label}: {note.note}")
- create_note(*, label: str | None = None, note: str, **other_settings) praw.models.ModNote
Create a moderator note on the author of this object in the subreddit it’s posted in.
- Parameters:
label – The label for the note. As of this writing, this can be one of the following:
"ABUSE_WARNING"
,"BAN"
,"BOT_BAN"
,"HELPFUL_USER"
,"PERMA_BAN"
,"SOLID_CONTRIBUTOR"
,"SPAM_WARNING"
,"SPAM_WATCH"
, orNone
(default:None
).note – The content of the note. As of this writing, this is limited to 250 characters.
other_settings – Additional keyword arguments are passed to
create()
.
- Returns:
The new
ModNote
object.
For example, to create a note on a
Submission
, try:reddit.submission("92dd8").mod.create_note(label="HELPFUL_USER", note="Test note")
RedditModNotes
- class praw.models.RedditModNotes(reddit: praw.Reddit)
Provides methods to interact with moderator notes at a global level.
Note
The authenticated user must be a moderator of the provided subreddit(s).
For example, the latest note for u/spez in r/redditdev and r/test, and for u/bboe in r/redditdev can be iterated through like so:
redditor = reddit.redditor("bboe") subreddit = reddit.subreddit("redditdev") pairs = [(subreddit, "spez"), ("test", "spez"), (subreddit, redditor)] for note in reddit.notes(pairs=pairs): print(f"{note.label}: {note.note}")
- __call__(*, all_notes: bool = False, pairs: List[Tuple[praw.models.Subreddit | str, Redditor | str]] | None = None, redditors: List[Redditor | str] | None = None, subreddits: List[str | praw.models.Subreddit] | None = None, things: List[Comment | Submission] | None = None, **generator_kwargs: Any) Generator[praw.models.ModNote, None, None]
Get note(s) for each subreddit/user pair, or
None
if they don’t have any.- Parameters:
all_notes –
Whether to return all notes or only the latest note for each subreddit/redditor pair (default:
False
).Note
Setting this to
True
will result in a request for each unique subreddit/redditor pair. Ifsubreddits
andredditors
are provided, this will make a request equivalent to number of redditors multiplied by the number of subreddits.pairs –
A list of subreddit/redditor tuples.
Note
Required if
subreddits
,redditors
, northings
are provided.redditors –
A list of redditors to return notes for. This parameter is used in tandem with
subreddits
to get notes from multiple subreddits for each of the provided redditors.Note
Required if
items
orthings
is not provided or ifsubreddits
is provided.subreddits –
A list of subreddits to return notes for. This parameter is used in tandem with
redditors
to get notes for multiple redditors from each of the provided subreddits.Note
Required if
items
orthings
is not provided or ifredditors
is provided.things – A list of comments and/or submissions to return notes for.
generator_kwargs – Additional keyword arguments passed to the generator. This parameter is ignored when
all_notes
isFalse
.
- Returns:
A generator that yields the most recent
ModNote
(orNone
if the user doesn’t have any notes) per entry in their relative order. Ifall_notes
isTrue
, this will yield all notes for each entry.
Note
This method will merge the subreddits and redditors provided from
pairs
,redditors
,subreddits
, andthings
.Note
This method accepts
Redditor
instances or redditor names andSubreddit
instances or subreddit names where applicable.For example, the latest note for u/spez in r/redditdev and r/test, and for u/bboe in r/redditdev can be iterated through like so:
redditor = reddit.redditor("bboe") subreddit = reddit.subreddit("redditdev") pairs = [(subreddit, "spez"), ("test", "spez"), (subreddit, redditor)] for note in reddit.notes(pairs=pairs): print(f"{note.label}: {note.note}")
For example, all the notes for u/spez and u/bboe in r/announcements, r/redditdev, and r/test can be iterated through like so:
redditor = reddit.redditor("bboe") subreddit = reddit.subreddit("redditdev") for note in reddit.notes( redditors=["spez", redditor], subreddits=["announcements", subreddit, "test"], all_notes=True, ): print(f"{note.label}: {note.note}")
For example, the latest note for the authors of the last 5 comments and submissions from r/test can be iterated through like so:
submissions = list(reddit.subreddit("test").new(limit=5)) comments = list(reddit.subreddit("test").comments(limit=5)) for note in reddit.notes(things=submissions + comments): print(f"{note.label}: {note.note}")
Note
Setting
all_notes
toTrue
will make a request for each redditor and subreddit combination. The previous example will make 6 requests.
- __init__(reddit: praw.Reddit)
Initialize a
BaseModNotes
instance.- Parameters:
reddit – An instance of
Reddit
.
- create(*, label: str | None = None, note: str, redditor: Redditor | str | None = None, subreddit: praw.models.Subreddit | str | None = None, thing: Comment | Submission | str | None = None, **other_settings: Any) praw.models.ModNote
Create a
ModNote
for a redditor in the specified subreddit.- Parameters:
label – The label for the note. As of this writing, this can be one of the following:
"ABUSE_WARNING"
,"BAN"
,"BOT_BAN"
,"HELPFUL_USER"
,"PERMA_BAN"
,"SOLID_CONTRIBUTOR"
,"SPAM_WARNING"
,"SPAM_WATCH"
, orNone
(default:None
).note – The content of the note. As of this writing, this is limited to 250 characters.
redditor –
The redditor to create the note for (default:
None
).Note
This parameter is required if
thing
is not provided or this is not called from aRedditor
instance (e.g.,reddit.redditor.notes
).subreddit –
The subreddit associated with the note (default:
None
).Note
This parameter is required if
thing
is not provided or this is not called from aSubreddit
instance (e.g.,reddit.subreddit.mod
).thing – Either the fullname of a comment/submission, a
Comment
, or aSubmission
to associate with the note.other_settings – Additional keyword arguments can be provided to handle new parameters as Reddit introduces them.
- Returns:
The new
ModNote
object.
For example, to create a note for u/spez in r/test:
reddit.subreddit("test").mod.notes.create( label="HELPFUL_USER", note="Test note", redditor="spez" ) # or reddit.redditor("spez").mod.notes.create( label="HELPFUL_USER", note="Test note", subreddit="test" ) # or reddit.notes.create( label="HELPFUL_USER", note="Test note", redditor="spez", subreddit="test" )
- delete(*, delete_all: bool = False, note_id: str | None = None, redditor: Redditor | str | None = None, subreddit: praw.models.Subreddit | str | None = None)
Delete note(s) for a redditor.
- Parameters:
delete_all –
When
True
, delete all notes for the specified redditor in the specified subreddit (default:False
).Note
This will make a request for each note.
note_id – The ID of the note to delete. This parameter is ignored if
delete_all
isTrue
.redditor –
The redditor to delete the note(s) for (default:
None
). Can be aRedditor
instance or a redditor name.Note
This parameter is required if this method is not called from a
Redditor
instance (e.g.,redditor.notes
).subreddit –
The subreddit to delete the note(s) from (default:
None
). Can be aSubreddit
instance or a subreddit name.Note
This parameter is required if this method is not called from a
Subreddit
instance (e.g.,reddit.subreddit.mod
).
For example, to delete a note with the ID
"ModNote_d324b280-5ecc-435d-8159-3e259e84e339"
, try:reddit.subreddit("test").mod.notes.delete( note_id="ModNote_d324b280-5ecc-435d-8159-3e259e84e339", redditor="spez" ) # or reddit.redditor("spez").notes.delete( note_id="ModNote_d324b280-5ecc-435d-8159-3e259e84e339", subreddit="test" ) # or reddit.notes.delete( note_id="ModNote_d324b280-5ecc-435d-8159-3e259e84e339", subreddit="test", redditor="spez", )
To delete all notes for u/spez, try:
reddit.subreddit("test").mod.notes.delete(delete_all=True, redditor="spez") # or reddit.redditor("spez").notes.delete(delete_all=True, subreddit="test") # or reddit.notes.delete(delete_all=True, subreddit="test", redditor="spez")
- things(*things: Comment | Submission, all_notes: bool | None = None, **generator_kwargs: Any) Generator[praw.models.ModNote, None, None]
Return notes associated with the author of a
Comment
orSubmission
.- Parameters:
things – One or more things to return notes on. Must be a
Comment
orSubmission
.all_notes –
Whether to return all notes, or only the latest (default:
True
if only one thing is provided otherwiseFalse
).Note
Setting this to
True
will result in a request for each thing.
- Returns:
A generator that yields the most recent
ModNote
(orNone
if the user doesn’t have any notes) per entry in their relative order. Ifall_notes
isTrue
, this will yield all notes for each entry.
For example, to get the latest note for the authors of the top 25 submissions in r/test:
submissions = reddit.subreddit("test").top(limit=25) for note in reddit.notes.things(*submissions): print(f"{note.label}: {note.note}")
For example, to get the latest note for the authors of the last 25 comments in r/test:
comments = reddit.subreddit("test").comments(limit=25) for note in reddit.notes.things(*comments): print(f"{note.label}: {note.note}")
RedditorModNotes
- class praw.models.RedditorModNotes(reddit: praw.Reddit, redditor: Redditor | str)
Provides methods to interact with moderator notes at the redditor level.
Note
The authenticated user must be a moderator of the provided subreddit(s).
For example, all the notes for u/spez in r/test can be iterated through like so:
redditor = reddit.redditor("spez") for note in redditor.notes.subreddits("test"): print(f"{note.label}: {note.note}")
- __init__(reddit: praw.Reddit, redditor: Redditor | str)
Initialize a
RedditorModNotes
instance.
- create(*, label: str | None = None, note: str, redditor: Redditor | str | None = None, subreddit: praw.models.Subreddit | str | None = None, thing: Comment | Submission | str | None = None, **other_settings: Any) praw.models.ModNote
Create a
ModNote
for a redditor in the specified subreddit.- Parameters:
label – The label for the note. As of this writing, this can be one of the following:
"ABUSE_WARNING"
,"BAN"
,"BOT_BAN"
,"HELPFUL_USER"
,"PERMA_BAN"
,"SOLID_CONTRIBUTOR"
,"SPAM_WARNING"
,"SPAM_WATCH"
, orNone
(default:None
).note – The content of the note. As of this writing, this is limited to 250 characters.
redditor –
The redditor to create the note for (default:
None
).Note
This parameter is required if
thing
is not provided or this is not called from aRedditor
instance (e.g.,reddit.redditor.notes
).subreddit –
The subreddit associated with the note (default:
None
).Note
This parameter is required if
thing
is not provided or this is not called from aSubreddit
instance (e.g.,reddit.subreddit.mod
).thing – Either the fullname of a comment/submission, a
Comment
, or aSubmission
to associate with the note.other_settings – Additional keyword arguments can be provided to handle new parameters as Reddit introduces them.
- Returns:
The new
ModNote
object.
For example, to create a note for u/spez in r/test:
reddit.subreddit("test").mod.notes.create( label="HELPFUL_USER", note="Test note", redditor="spez" ) # or reddit.redditor("spez").mod.notes.create( label="HELPFUL_USER", note="Test note", subreddit="test" ) # or reddit.notes.create( label="HELPFUL_USER", note="Test note", redditor="spez", subreddit="test" )
- delete(*, delete_all: bool = False, note_id: str | None = None, redditor: Redditor | str | None = None, subreddit: praw.models.Subreddit | str | None = None)
Delete note(s) for a redditor.
- Parameters:
delete_all –
When
True
, delete all notes for the specified redditor in the specified subreddit (default:False
).Note
This will make a request for each note.
note_id – The ID of the note to delete. This parameter is ignored if
delete_all
isTrue
.redditor –
The redditor to delete the note(s) for (default:
None
). Can be aRedditor
instance or a redditor name.Note
This parameter is required if this method is not called from a
Redditor
instance (e.g.,redditor.notes
).subreddit –
The subreddit to delete the note(s) from (default:
None
). Can be aSubreddit
instance or a subreddit name.Note
This parameter is required if this method is not called from a
Subreddit
instance (e.g.,reddit.subreddit.mod
).
For example, to delete a note with the ID
"ModNote_d324b280-5ecc-435d-8159-3e259e84e339"
, try:reddit.subreddit("test").mod.notes.delete( note_id="ModNote_d324b280-5ecc-435d-8159-3e259e84e339", redditor="spez" ) # or reddit.redditor("spez").notes.delete( note_id="ModNote_d324b280-5ecc-435d-8159-3e259e84e339", subreddit="test" ) # or reddit.notes.delete( note_id="ModNote_d324b280-5ecc-435d-8159-3e259e84e339", subreddit="test", redditor="spez", )
To delete all notes for u/spez, try:
reddit.subreddit("test").mod.notes.delete(delete_all=True, redditor="spez") # or reddit.redditor("spez").notes.delete(delete_all=True, subreddit="test") # or reddit.notes.delete(delete_all=True, subreddit="test", redditor="spez")
- subreddits(*subreddits: praw.models.Subreddit | str, all_notes: bool | None = None, **generator_kwargs: Any) Generator[praw.models.ModNote, None, None]
Return notes for this
Redditor
from one or more subreddits.- Parameters:
subreddits – One or more subreddits to retrieve the notes from. Must be either a
Subreddit
or a subreddit name.all_notes –
Whether to return all notes or only the latest note (default:
True
if only one subreddit is provided otherwiseFalse
).Note
Setting this to
True
will result in a request for each subreddit.
- Returns:
A generator that yields the most recent
ModNote
(orNone
if this redditor doesn’t have any notes) per subreddit in their relative order. Ifall_notes
isTrue
, this will yield all notes orNone
from each subreddit for this redditor.
For example, all the notes for u/spez in r/test can be iterated through like so:
redditor = reddit.redditor("spez") for note in redditor.notes.subreddits("test"): print(f"{note.label}: {note.note}")
For example, the latest note for u/spez from r/test and r/redditdev can be iterated through like so:
redditor = reddit.redditor("spez") subreddit = reddit.subreddit("redditdev") for note in redditor.notes.subreddits("test", subreddit): print(f"{note.label}: {note.note}")
For example, all the notes for u/spez in r/test and r/redditdev can be iterated through like so:
redditor = reddit.redditor("spez") subreddit = reddit.subreddit("redditdev") for note in redditor.notes.subreddits("test", subreddit, all_notes=True): print(f"{note.label}: {note.note}")
SubredditModNotes
- class praw.models.SubredditModNotes(reddit: praw.Reddit, subreddit: praw.models.Subreddit | str)
Provides methods to interact with moderator notes at the subreddit level.
Note
The authenticated user must be a moderator of this subreddit.
For example, all the notes for u/spez in r/test can be iterated through like so:
subreddit = reddit.subreddit("test") for note in subreddit.mod.notes.redditors("spez"): print(f"{note.label}: {note.note}")
- __init__(reddit: praw.Reddit, subreddit: praw.models.Subreddit | str)
Initialize a
SubredditModNotes
instance.
- create(*, label: str | None = None, note: str, redditor: Redditor | str | None = None, subreddit: praw.models.Subreddit | str | None = None, thing: Comment | Submission | str | None = None, **other_settings: Any) praw.models.ModNote
Create a
ModNote
for a redditor in the specified subreddit.- Parameters:
label – The label for the note. As of this writing, this can be one of the following:
"ABUSE_WARNING"
,"BAN"
,"BOT_BAN"
,"HELPFUL_USER"
,"PERMA_BAN"
,"SOLID_CONTRIBUTOR"
,"SPAM_WARNING"
,"SPAM_WATCH"
, orNone
(default:None
).note – The content of the note. As of this writing, this is limited to 250 characters.
redditor –
The redditor to create the note for (default:
None
).Note
This parameter is required if
thing
is not provided or this is not called from aRedditor
instance (e.g.,reddit.redditor.notes
).subreddit –
The subreddit associated with the note (default:
None
).Note
This parameter is required if
thing
is not provided or this is not called from aSubreddit
instance (e.g.,reddit.subreddit.mod
).thing – Either the fullname of a comment/submission, a
Comment
, or aSubmission
to associate with the note.other_settings – Additional keyword arguments can be provided to handle new parameters as Reddit introduces them.
- Returns:
The new
ModNote
object.
For example, to create a note for u/spez in r/test:
reddit.subreddit("test").mod.notes.create( label="HELPFUL_USER", note="Test note", redditor="spez" ) # or reddit.redditor("spez").mod.notes.create( label="HELPFUL_USER", note="Test note", subreddit="test" ) # or reddit.notes.create( label="HELPFUL_USER", note="Test note", redditor="spez", subreddit="test" )
- delete(*, delete_all: bool = False, note_id: str | None = None, redditor: Redditor | str | None = None, subreddit: praw.models.Subreddit | str | None = None)
Delete note(s) for a redditor.
- Parameters:
delete_all –
When
True
, delete all notes for the specified redditor in the specified subreddit (default:False
).Note
This will make a request for each note.
note_id – The ID of the note to delete. This parameter is ignored if
delete_all
isTrue
.redditor –
The redditor to delete the note(s) for (default:
None
). Can be aRedditor
instance or a redditor name.Note
This parameter is required if this method is not called from a
Redditor
instance (e.g.,redditor.notes
).subreddit –
The subreddit to delete the note(s) from (default:
None
). Can be aSubreddit
instance or a subreddit name.Note
This parameter is required if this method is not called from a
Subreddit
instance (e.g.,reddit.subreddit.mod
).
For example, to delete a note with the ID
"ModNote_d324b280-5ecc-435d-8159-3e259e84e339"
, try:reddit.subreddit("test").mod.notes.delete( note_id="ModNote_d324b280-5ecc-435d-8159-3e259e84e339", redditor="spez" ) # or reddit.redditor("spez").notes.delete( note_id="ModNote_d324b280-5ecc-435d-8159-3e259e84e339", subreddit="test" ) # or reddit.notes.delete( note_id="ModNote_d324b280-5ecc-435d-8159-3e259e84e339", subreddit="test", redditor="spez", )
To delete all notes for u/spez, try:
reddit.subreddit("test").mod.notes.delete(delete_all=True, redditor="spez") # or reddit.redditor("spez").notes.delete(delete_all=True, subreddit="test") # or reddit.notes.delete(delete_all=True, subreddit="test", redditor="spez")
- redditors(*redditors: Redditor | str, all_notes: bool | None = None, **generator_kwargs: Any) Generator[praw.models.ModNote, None, None]
Return notes from this
Subreddit
for one or more redditors.- Parameters:
redditors – One or more redditors to retrieve notes for. Must be either a
Redditor
or a redditor name.all_notes –
Whether to return all notes or only the latest note (default:
True
if only one redditor is provided otherwiseFalse
).Note
Setting this to
True
will result in a request for each redditor.
- Returns:
A generator that yields the most recent
ModNote
(orNone
if the user doesn’t have any notes in this subreddit) per redditor in their relative order. Ifall_notes
isTrue
, this will yield all notes for each redditor.
For example, all the notes for u/spez in r/test can be iterated through like so:
subreddit = reddit.subreddit("test") for note in subreddit.mod.notes.redditors("spez"): print(f"{note.label}: {note.note}")
For example, the latest note for u/spez and u/bboe from r/test can be iterated through like so:
subreddit = reddit.subreddit("test") redditor = reddit.redditor("bboe") for note in subreddit.mod.notes.redditors("spez", redditor): print(f"{note.label}: {note.note}")
For example, all the notes for both u/spez and u/bboe in r/test can be iterated through like so:
subreddit = reddit.subreddit("test") redditor = reddit.redditor("bboe") for note in subreddit.mod.notes.redditors("spez", redditor, all_notes=True): print(f"{note.label}: {note.note}")
CommentModeration
- class praw.models.reddit.comment.CommentModeration(comment: praw.models.Comment)
Provide a set of functions pertaining to
Comment
moderation.Example usage:
comment = reddit.comment("dkk4qjd") comment.mod.approve()
- __init__(comment: praw.models.Comment)
Initialize a
CommentModeration
instance.- Parameters:
comment – The comment to moderate.
- approve()
Approve a
Comment
orSubmission
.Approving a comment or submission reverts a removal, resets the report counter, adds a green check mark indicator (only visible to other moderators) on the website view, and sets the
approved_by
attribute to the authenticated user.Example usage:
# approve a comment: comment = reddit.comment("dkk4qjd") comment.mod.approve() # approve a submission: submission = reddit.submission("5or86n") submission.mod.approve()
- author_notes(**generator_kwargs) Generator[praw.models.ModNote, None, None]
Get the moderator notes for the author of this object in the subreddit it’s posted in.
- Parameters:
generator_kwargs – Additional keyword arguments are passed in the initialization of the moderator note generator.
- Returns:
A generator of
ModNote
.
For example, to list all notes the author of a submission, try:
for note in reddit.submission("92dd8").mod.author_notes(): print(f"{note.label}: {note.note}")
- create_note(*, label: str | None = None, note: str, **other_settings) praw.models.ModNote
Create a moderator note on the author of this object in the subreddit it’s posted in.
- Parameters:
label – The label for the note. As of this writing, this can be one of the following:
"ABUSE_WARNING"
,"BAN"
,"BOT_BAN"
,"HELPFUL_USER"
,"PERMA_BAN"
,"SOLID_CONTRIBUTOR"
,"SPAM_WARNING"
,"SPAM_WATCH"
, orNone
(default:None
).note – The content of the note. As of this writing, this is limited to 250 characters.
other_settings – Additional keyword arguments are passed to
create()
.
- Returns:
The new
ModNote
object.
For example, to create a note on a
Submission
, try:reddit.submission("92dd8").mod.create_note(label="HELPFUL_USER", note="Test note")
- distinguish(*, how: str = 'yes', sticky: bool = False)
Distinguish a
Comment
orSubmission
.- Parameters:
how – One of
"yes"
,"no"
,"admin"
, or"special"
."yes"
adds a moderator level distinguish."no"
removes any distinction."admin"
and"special"
require special user privileges to use (default"yes"
).sticky –
Comment
is stickied ifTrue
, placing it at the top of the comment page regardless of score. If thing is not a top-level comment, this parameter is silently ignored (defaultFalse
).
Example usage:
# distinguish and sticky a comment: comment = reddit.comment("dkk4qjd") comment.mod.distinguish(sticky=True) # undistinguish a submission: submission = reddit.submission("5or86n") submission.mod.distinguish(how="no")
See also
- ignore_reports()
Ignore future reports on a
Comment
orSubmission
.Calling this method will prevent future reports on this
Comment
orSubmission
from both triggering notifications and appearing in the various moderation listings. The report count will still increment on theComment
orSubmission
.Example usage:
# ignore future reports on a comment: comment = reddit.comment("dkk4qjd") comment.mod.ignore_reports() # ignore future reports on a submission: submission = reddit.submission("5or86n") submission.mod.ignore_reports()
See also
- lock()
Lock a
Comment
orSubmission
.Example usage:
# lock a comment: comment = reddit.comment("dkk4qjd") comment.mod.lock() # lock a submission: submission = reddit.submission("5or86n") submission.mod.lock()
See also
- remove(*, mod_note: str = '', spam: bool = False, reason_id: str | None = None)
Remove a
Comment
orSubmission
.- Parameters:
mod_note – A message for the other moderators.
spam – When
True
, use the removal to help train theSubreddit
’s spam filter (default:False
).reason_id – The removal reason ID.
If either
reason_id
ormod_note
are provided, a second API call is made to add the removal reason.Example usage:
# remove a comment and mark as spam: comment = reddit.comment("dkk4qjd") comment.mod.remove(spam=True) # remove a submission submission = reddit.submission("5or86n") submission.mod.remove() # remove a submission with a removal reason reason = reddit.subreddit.mod.removal_reasons["110ni21zo23ql"] submission = reddit.submission("5or86n") submission.mod.remove(reason_id=reason.id)
- send_removal_message(*, message: str, title: str = 'ignored', type: str = 'public') praw.models.Comment | None
Send a removal message for a
Comment
orSubmission
.Warning
The object has to be removed before giving it a removal reason. Remove the object with
remove()
. Trying to add a removal reason without removing the object will result inRedditAPIException
being thrown with anINVALID_ID
error_type.Reddit adds human-readable information about the object to the message.
- Parameters:
type – One of
"public"
,"private"
, or"private_exposed"
."public"
leaves a stickied comment on the post."private"
sends a modmail message with hidden username."private_exposed"
sends a modmail message without hidden username (default:"public"
).title – The short reason given in the message. Ignored if type is
"public"
.message – The body of the message.
- Returns:
The new
Comment
iftype
is"public"
.
- show()
Uncollapse a
Comment
that has been collapsed by Crowd Control.Example usage:
# Uncollapse a comment: comment = reddit.comment("dkk4qjd") comment.mod.show()
- undistinguish()
Remove mod, admin, or special distinguishing from an object.
Also unstickies the object if applicable.
Example usage:
# undistinguish a comment: comment = reddit.comment("dkk4qjd") comment.mod.undistinguish() # undistinguish a submission: submission = reddit.submission("5or86n") submission.mod.undistinguish()
See also
- unignore_reports()
Resume receiving future reports on a
Comment
orSubmission
.Future reports on this
Comment
orSubmission
will cause notifications, and appear in the various moderation listings.Example usage:
# accept future reports on a comment: comment = reddit.comment("dkk4qjd") comment.mod.unignore_reports() # accept future reports on a submission: submission = reddit.submission("5or86n") submission.mod.unignore_reports()
See also
- unlock()
Unlock a
Comment
orSubmission
.Example usage:
# unlock a comment: comment = reddit.comment("dkk4qjd") comment.mod.unlock() # unlock a submission: submission = reddit.submission("5or86n") submission.mod.unlock()
See also
RuleModeration
- class praw.models.reddit.rules.RuleModeration(rule: praw.models.Rule)
Contain methods used to moderate rules.
To delete
"No spam"
from r/test try:reddit.subreddit("test").rules["No spam"].mod.delete()
To update
"No spam"
from r/test try:reddit.subreddit("test").removal_reasons["No spam"].mod.update( description="Don't do this!", violation_reason="Spam post" )
- __init__(rule: praw.models.Rule)
Initialize a
RuleModeration
instance.
- delete()
Delete a rule from this subreddit.
To delete
"No spam"
from r/test try:reddit.subreddit("test").rules["No spam"].mod.delete()
- update(*, description: str | None = None, kind: str | None = None, short_name: str | None = None, violation_reason: str | None = None) praw.models.Rule
Update the rule from this subreddit.
Note
Existing values will be used for any unspecified arguments.
- Parameters:
description – The new description for the rule. Can be empty.
kind – The kind of item that the rule applies to. One of
"link"
,"comment"
, or"all"
.short_name – The name of the rule.
violation_reason – The reason that is shown on the report menu.
- Returns:
A Rule object containing the updated values.
To update
"No spam"
from r/test try:reddit.subreddit("test").removal_reasons["No spam"].mod.update( description="Don't do this!", violation_reason="Spam post" )
SubmissionModeration
- class praw.models.reddit.submission.SubmissionModeration(submission: praw.models.Submission)
Provide a set of functions pertaining to
Submission
moderation.Example usage:
submission = reddit.submission("8dmv8z") submission.mod.approve()
- __init__(submission: praw.models.Submission)
Initialize a
SubmissionModeration
instance.- Parameters:
submission – The submission to moderate.
- approve()
Approve a
Comment
orSubmission
.Approving a comment or submission reverts a removal, resets the report counter, adds a green check mark indicator (only visible to other moderators) on the website view, and sets the
approved_by
attribute to the authenticated user.Example usage:
# approve a comment: comment = reddit.comment("dkk4qjd") comment.mod.approve() # approve a submission: submission = reddit.submission("5or86n") submission.mod.approve()
- author_notes(**generator_kwargs) Generator[praw.models.ModNote, None, None]
Get the moderator notes for the author of this object in the subreddit it’s posted in.
- Parameters:
generator_kwargs – Additional keyword arguments are passed in the initialization of the moderator note generator.
- Returns:
A generator of
ModNote
.
For example, to list all notes the author of a submission, try:
for note in reddit.submission("92dd8").mod.author_notes(): print(f"{note.label}: {note.note}")
- contest_mode(*, state: bool = True)
Set contest mode for the comments of this submission.
- Parameters:
state –
True
enables contest mode andFalse
disables (default:True
).
Contest mode have the following effects:
The comment thread will default to being sorted randomly.
Replies to top-level comments will be hidden behind “[show replies]” buttons.
Scores will be hidden from non-moderators.
Scores accessed through the API (mobile apps, bots) will be obscured to “1” for non-moderators.
Example usage:
submission = reddit.submission("5or86n") submission.mod.contest_mode()
- create_note(*, label: str | None = None, note: str, **other_settings) praw.models.ModNote
Create a moderator note on the author of this object in the subreddit it’s posted in.
- Parameters:
label – The label for the note. As of this writing, this can be one of the following:
"ABUSE_WARNING"
,"BAN"
,"BOT_BAN"
,"HELPFUL_USER"
,"PERMA_BAN"
,"SOLID_CONTRIBUTOR"
,"SPAM_WARNING"
,"SPAM_WATCH"
, orNone
(default:None
).note – The content of the note. As of this writing, this is limited to 250 characters.
other_settings – Additional keyword arguments are passed to
create()
.
- Returns:
The new
ModNote
object.
For example, to create a note on a
Submission
, try:reddit.submission("92dd8").mod.create_note(label="HELPFUL_USER", note="Test note")
- distinguish(*, how: str = 'yes', sticky: bool = False)
Distinguish a
Comment
orSubmission
.- Parameters:
how – One of
"yes"
,"no"
,"admin"
, or"special"
."yes"
adds a moderator level distinguish."no"
removes any distinction."admin"
and"special"
require special user privileges to use (default"yes"
).sticky –
Comment
is stickied ifTrue
, placing it at the top of the comment page regardless of score. If thing is not a top-level comment, this parameter is silently ignored (defaultFalse
).
Example usage:
# distinguish and sticky a comment: comment = reddit.comment("dkk4qjd") comment.mod.distinguish(sticky=True) # undistinguish a submission: submission = reddit.submission("5or86n") submission.mod.distinguish(how="no")
See also
- flair(*, css_class: str = '', flair_template_id: str | None = None, text: str = '')
Set flair for the submission.
- Parameters:
css_class – The css class to associate with the flair html (default:
""
).flair_template_id – The flair template ID to use when flairing.
text – The flair text to associate with the
Submission
(default:""
).
This method can only be used by an authenticated user who is a moderator of the submission’s
Subreddit
.Example usage:
submission = reddit.submission("5or86n") submission.mod.flair(text="PRAW", css_class="bot")
- ignore_reports()
Ignore future reports on a
Comment
orSubmission
.Calling this method will prevent future reports on this
Comment
orSubmission
from both triggering notifications and appearing in the various moderation listings. The report count will still increment on theComment
orSubmission
.Example usage:
# ignore future reports on a comment: comment = reddit.comment("dkk4qjd") comment.mod.ignore_reports() # ignore future reports on a submission: submission = reddit.submission("5or86n") submission.mod.ignore_reports()
See also
- lock()
Lock a
Comment
orSubmission
.Example usage:
# lock a comment: comment = reddit.comment("dkk4qjd") comment.mod.lock() # lock a submission: submission = reddit.submission("5or86n") submission.mod.lock()
See also
- nsfw()
Mark as not safe for work.
This method can be used both by the submission author and moderators of the subreddit that the submission belongs to.
Example usage:
submission = reddit.subreddit("test").submit("nsfw test", selftext="nsfw") submission.mod.nsfw()
See also
- remove(*, mod_note: str = '', spam: bool = False, reason_id: str | None = None)
Remove a
Comment
orSubmission
.- Parameters:
mod_note – A message for the other moderators.
spam – When
True
, use the removal to help train theSubreddit
’s spam filter (default:False
).reason_id – The removal reason ID.
If either
reason_id
ormod_note
are provided, a second API call is made to add the removal reason.Example usage:
# remove a comment and mark as spam: comment = reddit.comment("dkk4qjd") comment.mod.remove(spam=True) # remove a submission submission = reddit.submission("5or86n") submission.mod.remove() # remove a submission with a removal reason reason = reddit.subreddit.mod.removal_reasons["110ni21zo23ql"] submission = reddit.submission("5or86n") submission.mod.remove(reason_id=reason.id)
- send_removal_message(*, message: str, title: str = 'ignored', type: str = 'public') praw.models.Comment | None
Send a removal message for a
Comment
orSubmission
.Warning
The object has to be removed before giving it a removal reason. Remove the object with
remove()
. Trying to add a removal reason without removing the object will result inRedditAPIException
being thrown with anINVALID_ID
error_type.Reddit adds human-readable information about the object to the message.
- Parameters:
type – One of
"public"
,"private"
, or"private_exposed"
."public"
leaves a stickied comment on the post."private"
sends a modmail message with hidden username."private_exposed"
sends a modmail message without hidden username (default:"public"
).title – The short reason given in the message. Ignored if type is
"public"
.message – The body of the message.
- Returns:
The new
Comment
iftype
is"public"
.
- set_original_content()
Mark as original content.
This method can be used by moderators of the subreddit that the submission belongs to. If the subreddit has enabled the Original Content beta feature in settings, then the submission’s author can use it as well.
Example usage:
submission = reddit.subreddit("test").submit("oc test", selftext="original") submission.mod.set_original_content()
See also
- sfw()
Mark as safe for work.
This method can be used both by the submission author and moderators of the subreddit that the submission belongs to.
Example usage:
submission = reddit.submission("5or86n") submission.mod.sfw()
See also
- spoiler()
Indicate that the submission contains spoilers.
This method can be used both by the submission author and moderators of the subreddit that the submission belongs to.
Example usage:
submission = reddit.submission("5or86n") submission.mod.spoiler()
See also
- sticky(*, bottom: bool = True, state: bool = True)
Set the submission’s sticky state in its subreddit.
- Parameters:
bottom – When
True
, set the submission as the bottom sticky. If no top sticky exists, this submission will become the top sticky regardless (default:True
).state –
True
sets the sticky for the submission andFalse
unsets (default:True
).
Note
When a submission is stickied two or more times, the Reddit API responds with a 409 error that is raised as a
Conflict
by prawcore. This method suppresses theseConflict
errors.This submission will replace the second stickied submission if one exists.
For example:
submission = reddit.submission("5or86n") submission.mod.sticky()
- suggested_sort(*, sort: str = 'blank')
Set the suggested sort for the comments of the submission.
- Parameters:
sort – Can be one of:
"confidence"
,"top"
,"new"
,"controversial"
,"old"
,"random"
,"qa"
, or"blank"
(default:"blank"
).
- undistinguish()
Remove mod, admin, or special distinguishing from an object.
Also unstickies the object if applicable.
Example usage:
# undistinguish a comment: comment = reddit.comment("dkk4qjd") comment.mod.undistinguish() # undistinguish a submission: submission = reddit.submission("5or86n") submission.mod.undistinguish()
See also
- unignore_reports()
Resume receiving future reports on a
Comment
orSubmission
.Future reports on this
Comment
orSubmission
will cause notifications, and appear in the various moderation listings.Example usage:
# accept future reports on a comment: comment = reddit.comment("dkk4qjd") comment.mod.unignore_reports() # accept future reports on a submission: submission = reddit.submission("5or86n") submission.mod.unignore_reports()
See also
- unlock()
Unlock a
Comment
orSubmission
.Example usage:
# unlock a comment: comment = reddit.comment("dkk4qjd") comment.mod.unlock() # unlock a submission: submission = reddit.submission("5or86n") submission.mod.unlock()
See also
- unset_original_content()
Indicate that the submission is not original content.
This method can be used by moderators of the subreddit that the submission belongs to. If the subreddit has enabled the Original Content beta feature in settings, then the submission’s author can use it as well.
Example usage:
submission = reddit.subreddit("test").submit("oc test", selftext="original") submission.mod.unset_original_content()
See also
- unspoiler()
Indicate that the submission does not contain spoilers.
This method can be used both by the submission author and moderators of the subreddit that the submission belongs to.
For example:
submission = reddit.subreddit("test").submit("not spoiler", selftext="spoiler") submission.mod.unspoiler()
See also
- update_crowd_control_level(level: int)
Change the Crowd Control level of the submission.
- Parameters:
level – An integer between 0 and 3.
Level Descriptions
Level
Name
Description
0
Off
Crowd Control will not action any of the submission’s comments.
1
Lenient
Comments from users who have negative karma in the subreddit are automatically collapsed.
2
Moderate
Comments from new users and users with negative karma in the subreddit are automatically collapsed.
3
Strict
Comments from users who haven’t joined the subreddit, new users, and users with negative karma in the subreddit are automatically collapsed.
Example usage:
submission = reddit.submission("745ryj") submission.mod.update_crowd_control_level(2)
See also
SubredditModeration
- class praw.models.reddit.subreddit.SubredditModeration(subreddit: praw.models.Subreddit)
Provides a set of moderation functions to a
Subreddit
.For example, to accept a moderation invite from r/test:
reddit.subreddit("test").mod.accept_invite()
- __init__(subreddit: praw.models.Subreddit)
Initialize a
SubredditModeration
instance.- Parameters:
subreddit – The subreddit to moderate.
- accept_invite()
Accept an invitation as a moderator of the community.
- edited(*, only: str | None = None, **generator_kwargs: Any) Iterator[praw.models.Comment | praw.models.Submission]
Return a
ListingGenerator
for edited comments and submissions.- Parameters:
only – If specified, one of
"comments"
or"submissions"
to yield only results of that type.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.To print all items in the edited queue try:
for item in reddit.subreddit("mod").mod.edited(limit=None): print(item)
- inbox(**generator_kwargs: Any) Iterator[praw.models.SubredditMessage]
Return a
ListingGenerator
for moderator messages.Warning
Legacy modmail is being deprecated in June 2021. Please see https://www.reddit.com/r/modnews/comments/mar9ha/even_more_modmail_improvements/ for more info.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.See also
unread()
for unread moderator messages.To print the last 5 moderator mail messages and their replies, try:
for message in reddit.subreddit("mod").mod.inbox(limit=5): print(f"From: {message.author}, Body: {message.body}") for reply in message.replies: print(f"From: {reply.author}, Body: {reply.body}")
- log(*, action: str | None = None, mod: praw.models.Redditor | str | None = None, **generator_kwargs: Any) Iterator[praw.models.ModAction]
Return a
ListingGenerator
for moderator log entries.- Parameters:
action – If given, only return log entries for the specified action.
mod – If given, only return log entries for actions made by the passed in redditor.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.To print the moderator and subreddit of the last 5 modlog entries try:
for log in reddit.subreddit("mod").mod.log(limit=5): print(f"Mod: {log.mod}, Subreddit: {log.subreddit}")
- modqueue(*, only: str | None = None, **generator_kwargs: Any) Iterator[praw.models.Comment | praw.models.Submission]
Return a
ListingGenerator
for modqueue items.- Parameters:
only – If specified, one of
"comments"
or"submissions"
to yield only results of that type.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.To print all modqueue items try:
for item in reddit.subreddit("mod").mod.modqueue(limit=None): print(item)
- notes() praw.models.SubredditModNotes
Provide an instance of
SubredditModNotes
.This provides an interface for managing moderator notes for this subreddit.
For example, all the notes for u/spez in r/test can be iterated through like so:
subreddit = reddit.subreddit("test") for note in subreddit.mod.notes.redditors("spez"): print(f"{note.label}: {note.note}")
- removal_reasons() SubredditRemovalReasons
Provide an instance of
SubredditRemovalReasons
.Use this attribute for interacting with a
Subreddit
’s removal reasons. For example to list all the removal reasons for a subreddit which you have theposts
moderator permission on, try:for removal_reason in reddit.subreddit("test").mod.removal_reasons: print(removal_reason)
A single removal reason can be lazily retrieved via:
reddit.subreddit("test").mod.removal_reasons["reason_id"]
Note
Attempting to access attributes of an nonexistent removal reason will result in a
ClientException
.
- reports(*, only: str | None = None, **generator_kwargs: Any) Iterator[praw.models.Comment | praw.models.Submission]
Return a
ListingGenerator
for reported comments and submissions.- Parameters:
only – If specified, one of
"comments"
or"submissions"
to yield only results of that type.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.To print the user and mod report reasons in the report queue try:
for reported_item in reddit.subreddit("mod").mod.reports(): print(f"User Reports: {reported_item.user_reports}") print(f"Mod Reports: {reported_item.mod_reports}")
- spam(*, only: str | None = None, **generator_kwargs: Any) Iterator[praw.models.Comment | praw.models.Submission]
Return a
ListingGenerator
for spam comments and submissions.- Parameters:
only – If specified, one of
"comments"
or"submissions"
to yield only results of that type.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.To print the items in the spam queue try:
for item in reddit.subreddit("mod").mod.spam(): print(item)
- stream() praw.models.reddit.subreddit.SubredditModerationStream
Provide an instance of
SubredditModerationStream
.Streams can be used to indefinitely retrieve Moderator only items from
SubredditModeration
made to moderated subreddits, like:for log in reddit.subreddit("mod").mod.stream.log(): print(f"Mod: {log.mod}, Subreddit: {log.subreddit}")
- unmoderated(**generator_kwargs: Any) Iterator[praw.models.Submission]
Return a
ListingGenerator
for unmoderated submissions.Additional keyword arguments are passed in the initialization of
ListingGenerator
.To print the items in the unmoderated queue try:
for item in reddit.subreddit("mod").mod.unmoderated(): print(item)
- unread(**generator_kwargs: Any) Iterator[praw.models.SubredditMessage]
Return a
ListingGenerator
for unread moderator messages.Warning
Legacy modmail is being deprecated in June 2021. Please see https://www.reddit.com/r/modnews/comments/mar9ha/even_more_modmail_improvements/ for more info.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.See also
inbox()
for all messages.To print the mail in the unread modmail queue try:
for message in reddit.subreddit("mod").mod.unread(): print(f"From: {message.author}, To: {message.dest}")
- update(**settings: str | int | bool) Dict[str, str | int | bool]
Update the
Subreddit
’s settings.See https://www.reddit.com/dev/api#POST_api_site_admin for the full list.
- Parameters:
all_original_content – Mandate all submissions to be original content only.
allow_chat_post_creation – Allow users to create chat submissions.
allow_images – Allow users to upload images using the native image hosting.
allow_polls – Allow users to post polls to the subreddit.
allow_post_crossposts – Allow users to crosspost submissions from other subreddits.
allow_videos – Allow users to upload videos using the native image hosting.
collapse_deleted_comments – Collapse deleted and removed comments on comments pages by default.
comment_score_hide_mins – The number of minutes to hide comment scores.
content_options – The types of submissions users can make. One of
"any"
,"link"
, or"self"
.crowd_control_chat_level – Controls the crowd control level for chat rooms. Goes from 0-3.
crowd_control_level – Controls the crowd control level for submissions. Goes from 0-3.
crowd_control_mode – Enables/disables crowd control.
default_set – Allow the subreddit to appear on r/all as well as the default and trending lists.
disable_contributor_requests – Specifies whether redditors may send automated modmail messages requesting approval as a submitter.
exclude_banned_modqueue – Exclude posts by site-wide banned users from modqueue/unmoderated.
free_form_reports – Allow users to specify custom reasons in the report menu.
header_hover_text – The text seen when hovering over the snoo.
hide_ads – Don’t show ads within this subreddit. Only applies to Premium-user only subreddits.
key_color – A 6-digit rgb hex color (e.g.,
"#AABBCC"
), used as a thematic color for your subreddit on mobile.language – A valid IETF language tag (underscore separated).
original_content_tag_enabled – Enables the use of the
original content
label for submissions.over_18 – Viewers must be over 18 years old (i.e., NSFW).
public_description – Public description blurb. Appears in search results and on the landing page for private subreddits.
restrict_commenting – Specifies whether approved users have the ability to comment.
restrict_posting – Specifies whether approved users have the ability to submit posts.
show_media – Show thumbnails on submissions.
show_media_preview – Expand media previews on comments pages.
spam_comments – Spam filter strength for comments. One of
"all"
,"low"
, or"high"
.spam_links – Spam filter strength for links. One of
"all"
,"low"
, or"high"
.spam_selfposts – Spam filter strength for selfposts. One of
"all"
,"low"
, or"high"
.spoilers_enabled – Enable marking posts as containing spoilers.
submit_link_label – Custom label for submit link button (
None
for default).submit_text – Text to show on submission page.
submit_text_label – Custom label for submit text post button (
None
for default).subreddit_type – One of
"archived"
,"employees_only"
,"gold_only"
,gold_restricted
,"private"
,"public"
, or"restricted"
.suggested_comment_sort – All comment threads will use this sorting method by default. Leave
None
, or choose one of"confidence"
,"controversial"
,"live"
,"new"
,"old"
,"qa"
,"random"
, or"top"
.title – The title of the subreddit.
welcome_message_enabled – Enables the subreddit welcome message.
welcome_message_text – The text to be used as a welcome message. A welcome message is sent to all new subscribers by a Reddit bot.
wiki_edit_age – Account age, in days, required to edit and create wiki pages.
wiki_edit_karma – Subreddit karma required to edit and create wiki pages.
wikimode – One of
"anyone"
,"disabled"
, or"modonly"
.
Note
Updating the subreddit sidebar on old reddit (
description
) is no longer supported using this method. You can update the sidebar by editing the"config/sidebar"
wiki page. For example:sidebar = reddit.subreddit("test").wiki["config/sidebar"] sidebar.edit(content="new sidebar content")
Additional keyword arguments can be provided to handle new settings as Reddit introduces them.
Settings that are documented here and aren’t explicitly set by you in a call to
SubredditModeration.update()
should retain their current value. If they do not, please file a bug.
SubredditRulesModeration
- class praw.models.reddit.rules.SubredditRulesModeration(subreddit_rules: SubredditRules)
Contain methods to moderate subreddit rules as a whole.
To add rule
"No spam"
to r/test try:reddit.subreddit("test").rules.mod.add( short_name="No spam", kind="all", description="Do not spam. Spam bad" )
To move the fourth rule to the first position, and then to move the prior first rule to where the third rule originally was in r/test:
subreddit = reddit.subreddit("test") rules = list(subreddit.rules) new_rules = rules[3:4] + rules[1:3] + rules[0:1] + rules[4:] # Alternate: [rules[3]] + rules[1:3] + [rules[0]] + rules[4:] new_rule_list = subreddit.rules.mod.reorder(new_rules)
- __init__(subreddit_rules: SubredditRules)
Initialize a
SubredditRulesModeration
instance.
- add(*, description: str = '', kind: str, short_name: str, violation_reason: str | None = None) praw.models.Rule
Add a removal reason to this subreddit.
- Parameters:
description – The description for the rule.
kind – The kind of item that the rule applies to. One of
"link"
,"comment"
, or"all"
.short_name – The name of the rule.
violation_reason – The reason that is shown on the report menu. If a violation reason is not specified, the short name will be used as the violation reason.
- Returns:
The added
Rule
.
To add rule
"No spam"
to r/test try:reddit.subreddit("test").rules.mod.add( short_name="No spam", kind="all", description="Do not spam. Spam bad" )
- reorder(rule_list: List[praw.models.Rule]) List[praw.models.Rule]
Reorder the rules of a subreddit.
- Parameters:
rule_list – The list of rules, in the wanted order. Each index of the list indicates the position of the rule.
- Returns:
A list containing the rules in the specified order.
For example, to move the fourth rule to the first position, and then to move the prior first rule to where the third rule originally was in r/test:
subreddit = reddit.subreddit("test") rules = list(subreddit.rules) new_rules = rules[3:4] + rules[1:3] + rules[0:1] + rules[4:] # Alternate: [rules[3]] + rules[1:3] + [rules[0]] + rules[4:] new_rule_list = subreddit.rules.mod.reorder(new_rules)
SubredditWidgetsModeration
- class praw.models.SubredditWidgetsModeration(subreddit: praw.models.Subreddit, reddit: praw.Reddit)
Class for moderating a
Subreddit
’s widgets.Get an instance of this class from
SubredditWidgets.mod
.Example usage:
styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} reddit.subreddit("test").widgets.mod.add_text_area( short_name="My title", text="**bold text**", styles=styles )
Note
To use this class’s methods, the authenticated user must be a moderator with appropriate permissions.
- __init__(subreddit: praw.models.Subreddit, reddit: praw.Reddit)
Initialize a
SubredditWidgetsModeration
instance.
- add_button_widget(*, buttons: List[Dict[str, Dict[str, str] | str | int | Dict[str, str | int]]], description: str, short_name: str, styles: Dict[str, str], **other_settings) praw.models.ButtonWidget
Add and return a
ButtonWidget
.- Parameters:
buttons –
A list of dictionaries describing buttons, as specified in Reddit docs. As of this writing, the format is:
Each button is either a text button or an image button. A text button looks like this:
{ "kind": "text", "text": a string no longer than 30 characters, "url": a valid URL, "color": a 6-digit rgb hex color, e.g., `#AABBCC`, "textColor": a 6-digit rgb hex color, e.g., `#AABBCC`, "fillColor": a 6-digit rgb hex color, e.g., `#AABBCC`, "hoverState": {...} }
An image button looks like this:
{ "kind": "image", "text": a string no longer than 30 characters, "linkUrl": a valid URL, "url": a valid URL of a Reddit-hosted image, "height": an integer, "width": an integer, "hoverState": {...} }
Both types of buttons have the field
hoverState
. The field does not have to be included (it is optional). If it is included, it can be one of two types:"text"
or"image"
. A texthoverState
looks like this:{ "kind": "text", "text": a string no longer than 30 characters, "color": a 6-digit rgb hex color, e.g., `#AABBCC`, "textColor": a 6-digit rgb hex color, e.g., `#AABBCC`, "fillColor": a 6-digit rgb hex color, e.g., `#AABBCC` }
An image
hoverState
looks like this:{ "kind": "image", "url": a valid URL of a Reddit-hosted image, "height": an integer, "width": an integer }
Note
The method
upload_image()
can be used to upload images to Reddit for aurl
field that holds a Reddit-hosted image.Note
An image
hoverState
may be paired with a text widget, and a texthoverState
may be paired with an image widget.description – Markdown text to describe the widget.
short_name – A name for the widget, no longer than 30 characters.
styles – A dictionary with keys
"backgroundColor"
and"headerColor"
, and values of hex colors. For example,{"backgroundColor": "#FFFF66", "headerColor": "#3333EE"}
.
- Returns:
The created
ButtonWidget
.
Example usage:
widget_moderation = reddit.subreddit("test").widgets.mod my_image = widget_moderation.upload_image("/path/to/pic.jpg") buttons = [ { "kind": "text", "text": "View source", "url": "https://github.com/praw-dev/praw", "color": "#FF0000", "textColor": "#00FF00", "fillColor": "#0000FF", "hoverState": { "kind": "text", "text": "ecruos weiV", "color": "#FFFFFF", "textColor": "#000000", "fillColor": "#0000FF", }, }, { "kind": "image", "text": "View documentation", "linkUrl": "https://praw.readthedocs.io", "url": my_image, "height": 200, "width": 200, "hoverState": {"kind": "image", "url": my_image, "height": 200, "width": 200}, }, ] styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} new_widget = widget_moderation.add_button_widget( short_name="Things to click", description="Click some of these *cool* links!", buttons=buttons, styles=styles, )
- add_calendar(*, configuration: Dict[str, bool | int], google_calendar_id: str, requires_sync: bool, short_name: str, styles: Dict[str, str], **other_settings) praw.models.Calendar
Add and return a
Calendar
widget.- Parameters:
configuration –
A dictionary as specified in Reddit docs. For example:
{ "numEvents": 10, "showDate": True, "showDescription": False, "showLocation": False, "showTime": True, "showTitle": True, }
google_calendar_id – An email-style calendar ID. To share a Google Calendar, make it public, then find the “Calendar ID”.
requires_sync – Whether the calendar needs synchronization.
short_name – A name for the widget, no longer than 30 characters.
styles – A dictionary with keys
"backgroundColor"
and"headerColor"
, and values of hex colors. For example,{"backgroundColor": "#FFFF66", "headerColor": "#3333EE"}
.
- Returns:
The created
Calendar
.
Example usage:
widget_moderation = reddit.subreddit("test").widgets.mod styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} config = { "numEvents": 10, "showDate": True, "showDescription": False, "showLocation": False, "showTime": True, "showTitle": True, } calendar_id = "y6nm89jy427drk8l71w75w9wjn@group.calendar.google.com" new_widget = widget_moderation.add_calendar( short_name="Upcoming Events", google_calendar_id=calendar_id, requires_sync=True, configuration=config, styles=styles, )
- add_community_list(*, data: List[str | praw.models.Subreddit], description: str = '', short_name: str, styles: Dict[str, str], **other_settings) praw.models.CommunityList
Add and return a
CommunityList
widget.- Parameters:
data – A list of subreddits. Subreddits can be represented as
str
or asSubreddit
. These types may be mixed within the list.description – A string containing Markdown (default:
""
).short_name – A name for the widget, no longer than 30 characters.
styles – A dictionary with keys
"backgroundColor"
and"headerColor"
, and values of hex colors. For example,{"backgroundColor": "#FFFF66", "headerColor": "#3333EE"}
.
- Returns:
The created
CommunityList
.
Example usage:
widget_moderation = reddit.subreddit("test").widgets.mod styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} subreddits = ["learnpython", reddit.subreddit("redditdev")] new_widget = widget_moderation.add_community_list( short_name="My fav subs", data=subreddits, styles=styles, description="description" )
- add_custom_widget(*, css: str, height: int, image_data: List[Dict[str, str | int]], short_name: str, styles: Dict[str, str], text: str, **other_settings) praw.models.CustomWidget
Add and return a
CustomWidget
.- Parameters:
css –
The CSS for the widget, no longer than 100000 characters.
Note
As of this writing, Reddit will not accept empty CSS. If you wish to create a custom widget without CSS, consider using
"/**/"
(an empty comment) as your CSS.height – The height of the widget, between 50 and 500.
image_data –
A list of dictionaries as specified in Reddit docs. Each dictionary represents an image and has the key
"url"
which maps to the URL of an image hosted on Reddit’s servers. Images should be uploaded usingupload_image()
.For example:
[ { "url": "https://some.link", # from upload_image() "width": 600, "height": 450, "name": "logo", }, { "url": "https://other.link", # from upload_image() "width": 450, "height": 600, "name": "icon", }, ]
short_name – A name for the widget, no longer than 30 characters.
styles – A dictionary with keys
"backgroundColor"
and"headerColor"
, and values of hex colors. For example,{"backgroundColor": "#FFFF66", "headerColor": "#3333EE"}
.text – The Markdown text displayed in the widget.
- Returns:
The created
CustomWidget
.
Example usage:
widget_moderation = reddit.subreddit("test").widgets.mod image_paths = ["/path/to/image1.jpg", "/path/to/image2.png"] image_urls = [widget_moderation.upload_image(img_path) for img_path in image_paths] image_data = [ {"width": 600, "height": 450, "name": "logo", "url": image_urls[0]}, {"width": 450, "height": 600, "name": "icon", "url": image_urls[1]}, ] styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} new_widget = widget_moderation.add_custom_widget( image_short_name="My widget", text="# Hello world!", css="/**/", height=200, image_data=image_data, styles=styles, )
- add_image_widget(*, data: List[Dict[str, str | int]], short_name: str, styles: Dict[str, str], **other_settings) praw.models.ImageWidget
Add and return an
ImageWidget
.- Parameters:
data –
A list of dictionaries as specified in Reddit docs. Each dictionary has the key
"url"
which maps to the URL of an image hosted on Reddit’s servers. Images should be uploaded usingupload_image()
.For example:
[ { "url": "https://some.link", # from upload_image() "width": 600, "height": 450, "linkUrl": "https://github.com/praw-dev/praw", }, { "url": "https://other.link", # from upload_image() "width": 450, "height": 600, "linkUrl": "https://praw.readthedocs.io", }, ]
short_name – A name for the widget, no longer than 30 characters.
styles – A dictionary with keys
"backgroundColor"
and"headerColor"
, and values of hex colors. For example,{"backgroundColor": "#FFFF66", "headerColor": "#3333EE"}
.
- Returns:
The created
ImageWidget
.
Example usage:
widget_moderation = reddit.subreddit("test").widgets.mod image_paths = ["/path/to/image1.jpg", "/path/to/image2.png"] image_data = [ { "width": 600, "height": 450, "linkUrl": "", "url": widget_moderation.upload_image(img_path), } for img_path in image_paths ] styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} new_widget = widget_moderation.add_image_widget( short_name="My cool pictures", data=image_data, styles=styles )
Add and return a
Menu
widget.- Parameters:
data –
A list of dictionaries describing menu contents, as specified in Reddit docs. As of this writing, the format is:
[ { "text": a string no longer than 20 characters, "url": a valid URL }, OR { "children": [ { "text": a string no longer than 20 characters, "url": a valid URL, }, ... ], "text": a string no longer than 20 characters, }, ... ]
- Returns:
The created
Menu
.
Example usage:
widget_moderation = reddit.subreddit("test").widgets.mod menu_contents = [ {"text": "My homepage", "url": "https://example.com"}, { "text": "Python packages", "children": [ {"text": "PRAW", "url": "https://praw.readthedocs.io/"}, {"text": "requests", "url": "https://docs.python-requests.org/"}, ], }, {"text": "Reddit homepage", "url": "https://reddit.com"}, ] new_widget = widget_moderation.add_menu(data=menu_contents)
- add_post_flair_widget(*, display: str, order: List[str], short_name: str, styles: Dict[str, str], **other_settings) praw.models.PostFlairWidget
Add and return a
PostFlairWidget
.- Parameters:
display – Display style. Either
"cloud"
or"list"
.order –
A list of flair template IDs. You can get all flair template IDs in a subreddit with:
flairs = [f["id"] for f in subreddit.flair.link_templates]
short_name – A name for the widget, no longer than 30 characters.
styles – A dictionary with keys
"backgroundColor"
and"headerColor"
, and values of hex colors. For example,{"backgroundColor": "#FFFF66", "headerColor": "#3333EE"}
.
- Returns:
The created
PostFlairWidget
.
Example usage:
subreddit = reddit.subreddit("test") widget_moderation = subreddit.widgets.mod flairs = [f["id"] for f in subreddit.flair.link_templates] styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} new_widget = widget_moderation.add_post_flair_widget( short_name="Some flairs", display="list", order=flairs, styles=styles )
- add_text_area(*, short_name: str, styles: Dict[str, str], text: str, **other_settings) praw.models.TextArea
Add and return a
TextArea
widget.- Parameters:
short_name – A name for the widget, no longer than 30 characters.
styles – A dictionary with keys
"backgroundColor"
and"headerColor"
, and values of hex colors. For example,{"backgroundColor": "#FFFF66", "headerColor": "#3333EE"}
.text – The Markdown text displayed in the widget.
- Returns:
The created
TextArea
.
Example usage:
widget_moderation = reddit.subreddit("test").widgets.mod styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} new_widget = widget_moderation.add_text_area( short_name="My cool title", text="*Hello* **world**!", styles=styles )
- reorder(new_order: List[praw.models.ButtonWidget | praw.models.Calendar | praw.models.CommunityList | praw.models.CustomWidget | praw.models.IDCard | praw.models.ImageWidget | praw.models.Menu | praw.models.ModeratorsWidget | praw.models.PostFlairWidget | praw.models.RulesWidget | praw.models.TextArea | praw.models.Widget | str], *, section: str = 'sidebar')
Reorder the widgets.
- Parameters:
new_order – A list of widgets. Represented as a list that contains
Widget
objects, or widget IDs as strings. These types may be mixed.section – The section to reorder (default:
"sidebar"
).
Example usage:
widgets = reddit.subreddit("test").widgets order = list(widgets.sidebar) order.reverse() widgets.mod.reorder(order)
- upload_image(file_path: str) str
Upload an image to Reddit and get the URL.
- Parameters:
file_path – The path to the local file.
- Returns:
The URL of the uploaded image as a
str
.
This method is used to upload images for widgets. For example, it can be used in conjunction with
add_image_widget()
,add_custom_widget()
, andadd_button_widget()
.Example usage:
my_sub = reddit.subreddit("test") image_url = my_sub.widgets.mod.upload_image("/path/to/image.jpg") image_data = [{"width": 300, "height": 300, "url": image_url, "linkUrl": ""}] styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} my_sub.widgets.mod.add_image_widget( short_name="My cool pictures", data=image_data, styles=styles )
ThingModerationMixin
- class praw.models.reddit.mixins.ThingModerationMixin
Provides moderation methods for
Comment
s andSubmission
s.- __init__()
- approve()
Approve a
Comment
orSubmission
.Approving a comment or submission reverts a removal, resets the report counter, adds a green check mark indicator (only visible to other moderators) on the website view, and sets the
approved_by
attribute to the authenticated user.Example usage:
# approve a comment: comment = reddit.comment("dkk4qjd") comment.mod.approve() # approve a submission: submission = reddit.submission("5or86n") submission.mod.approve()
- author_notes(**generator_kwargs) Generator[praw.models.ModNote, None, None]
Get the moderator notes for the author of this object in the subreddit it’s posted in.
- Parameters:
generator_kwargs – Additional keyword arguments are passed in the initialization of the moderator note generator.
- Returns:
A generator of
ModNote
.
For example, to list all notes the author of a submission, try:
for note in reddit.submission("92dd8").mod.author_notes(): print(f"{note.label}: {note.note}")
- create_note(*, label: str | None = None, note: str, **other_settings) praw.models.ModNote
Create a moderator note on the author of this object in the subreddit it’s posted in.
- Parameters:
label – The label for the note. As of this writing, this can be one of the following:
"ABUSE_WARNING"
,"BAN"
,"BOT_BAN"
,"HELPFUL_USER"
,"PERMA_BAN"
,"SOLID_CONTRIBUTOR"
,"SPAM_WARNING"
,"SPAM_WATCH"
, orNone
(default:None
).note – The content of the note. As of this writing, this is limited to 250 characters.
other_settings – Additional keyword arguments are passed to
create()
.
- Returns:
The new
ModNote
object.
For example, to create a note on a
Submission
, try:reddit.submission("92dd8").mod.create_note(label="HELPFUL_USER", note="Test note")
- distinguish(*, how: str = 'yes', sticky: bool = False)
Distinguish a
Comment
orSubmission
.- Parameters:
how – One of
"yes"
,"no"
,"admin"
, or"special"
."yes"
adds a moderator level distinguish."no"
removes any distinction."admin"
and"special"
require special user privileges to use (default"yes"
).sticky –
Comment
is stickied ifTrue
, placing it at the top of the comment page regardless of score. If thing is not a top-level comment, this parameter is silently ignored (defaultFalse
).
Example usage:
# distinguish and sticky a comment: comment = reddit.comment("dkk4qjd") comment.mod.distinguish(sticky=True) # undistinguish a submission: submission = reddit.submission("5or86n") submission.mod.distinguish(how="no")
See also
- ignore_reports()
Ignore future reports on a
Comment
orSubmission
.Calling this method will prevent future reports on this
Comment
orSubmission
from both triggering notifications and appearing in the various moderation listings. The report count will still increment on theComment
orSubmission
.Example usage:
# ignore future reports on a comment: comment = reddit.comment("dkk4qjd") comment.mod.ignore_reports() # ignore future reports on a submission: submission = reddit.submission("5or86n") submission.mod.ignore_reports()
See also
- lock()
Lock a
Comment
orSubmission
.Example usage:
# lock a comment: comment = reddit.comment("dkk4qjd") comment.mod.lock() # lock a submission: submission = reddit.submission("5or86n") submission.mod.lock()
See also
- remove(*, mod_note: str = '', spam: bool = False, reason_id: str | None = None)
Remove a
Comment
orSubmission
.- Parameters:
mod_note – A message for the other moderators.
spam – When
True
, use the removal to help train theSubreddit
’s spam filter (default:False
).reason_id – The removal reason ID.
If either
reason_id
ormod_note
are provided, a second API call is made to add the removal reason.Example usage:
# remove a comment and mark as spam: comment = reddit.comment("dkk4qjd") comment.mod.remove(spam=True) # remove a submission submission = reddit.submission("5or86n") submission.mod.remove() # remove a submission with a removal reason reason = reddit.subreddit.mod.removal_reasons["110ni21zo23ql"] submission = reddit.submission("5or86n") submission.mod.remove(reason_id=reason.id)
- send_removal_message(*, message: str, title: str = 'ignored', type: str = 'public') praw.models.Comment | None
Send a removal message for a
Comment
orSubmission
.Warning
The object has to be removed before giving it a removal reason. Remove the object with
remove()
. Trying to add a removal reason without removing the object will result inRedditAPIException
being thrown with anINVALID_ID
error_type.Reddit adds human-readable information about the object to the message.
- Parameters:
type – One of
"public"
,"private"
, or"private_exposed"
."public"
leaves a stickied comment on the post."private"
sends a modmail message with hidden username."private_exposed"
sends a modmail message without hidden username (default:"public"
).title – The short reason given in the message. Ignored if type is
"public"
.message – The body of the message.
- Returns:
The new
Comment
iftype
is"public"
.
- undistinguish()
Remove mod, admin, or special distinguishing from an object.
Also unstickies the object if applicable.
Example usage:
# undistinguish a comment: comment = reddit.comment("dkk4qjd") comment.mod.undistinguish() # undistinguish a submission: submission = reddit.submission("5or86n") submission.mod.undistinguish()
See also
- unignore_reports()
Resume receiving future reports on a
Comment
orSubmission
.Future reports on this
Comment
orSubmission
will cause notifications, and appear in the various moderation listings.Example usage:
# accept future reports on a comment: comment = reddit.comment("dkk4qjd") comment.mod.unignore_reports() # accept future reports on a submission: submission = reddit.submission("5or86n") submission.mod.unignore_reports()
See also
- unlock()
Unlock a
Comment
orSubmission
.Example usage:
# unlock a comment: comment = reddit.comment("dkk4qjd") comment.mod.unlock() # unlock a submission: submission = reddit.submission("5or86n") submission.mod.unlock()
See also
UserSubredditModeration
- class praw.models.reddit.user_subreddit.UserSubredditModeration(subreddit: praw.models.Subreddit)
Provides a set of moderation functions to a
UserSubreddit
.For example, to accept a moderation invite from the user subreddit of u/spez:
reddit.subreddit("test").mod.accept_invite()
- __init__(subreddit: praw.models.Subreddit)
Initialize a
SubredditModeration
instance.- Parameters:
subreddit – The subreddit to moderate.
- accept_invite()
Accept an invitation as a moderator of the community.
- edited(*, only: str | None = None, **generator_kwargs: Any) Iterator[praw.models.Comment | praw.models.Submission]
Return a
ListingGenerator
for edited comments and submissions.- Parameters:
only – If specified, one of
"comments"
or"submissions"
to yield only results of that type.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.To print all items in the edited queue try:
for item in reddit.subreddit("mod").mod.edited(limit=None): print(item)
- inbox(**generator_kwargs: Any) Iterator[praw.models.SubredditMessage]
Return a
ListingGenerator
for moderator messages.Warning
Legacy modmail is being deprecated in June 2021. Please see https://www.reddit.com/r/modnews/comments/mar9ha/even_more_modmail_improvements/ for more info.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.See also
unread()
for unread moderator messages.To print the last 5 moderator mail messages and their replies, try:
for message in reddit.subreddit("mod").mod.inbox(limit=5): print(f"From: {message.author}, Body: {message.body}") for reply in message.replies: print(f"From: {reply.author}, Body: {reply.body}")
- log(*, action: str | None = None, mod: praw.models.Redditor | str | None = None, **generator_kwargs: Any) Iterator[praw.models.ModAction]
Return a
ListingGenerator
for moderator log entries.- Parameters:
action – If given, only return log entries for the specified action.
mod – If given, only return log entries for actions made by the passed in redditor.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.To print the moderator and subreddit of the last 5 modlog entries try:
for log in reddit.subreddit("mod").mod.log(limit=5): print(f"Mod: {log.mod}, Subreddit: {log.subreddit}")
- modqueue(*, only: str | None = None, **generator_kwargs: Any) Iterator[praw.models.Comment | praw.models.Submission]
Return a
ListingGenerator
for modqueue items.- Parameters:
only – If specified, one of
"comments"
or"submissions"
to yield only results of that type.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.To print all modqueue items try:
for item in reddit.subreddit("mod").mod.modqueue(limit=None): print(item)
- notes() praw.models.SubredditModNotes
Provide an instance of
SubredditModNotes
.This provides an interface for managing moderator notes for this subreddit.
For example, all the notes for u/spez in r/test can be iterated through like so:
subreddit = reddit.subreddit("test") for note in subreddit.mod.notes.redditors("spez"): print(f"{note.label}: {note.note}")
- removal_reasons() SubredditRemovalReasons
Provide an instance of
SubredditRemovalReasons
.Use this attribute for interacting with a
Subreddit
’s removal reasons. For example to list all the removal reasons for a subreddit which you have theposts
moderator permission on, try:for removal_reason in reddit.subreddit("test").mod.removal_reasons: print(removal_reason)
A single removal reason can be lazily retrieved via:
reddit.subreddit("test").mod.removal_reasons["reason_id"]
Note
Attempting to access attributes of an nonexistent removal reason will result in a
ClientException
.
- reports(*, only: str | None = None, **generator_kwargs: Any) Iterator[praw.models.Comment | praw.models.Submission]
Return a
ListingGenerator
for reported comments and submissions.- Parameters:
only – If specified, one of
"comments"
or"submissions"
to yield only results of that type.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.To print the user and mod report reasons in the report queue try:
for reported_item in reddit.subreddit("mod").mod.reports(): print(f"User Reports: {reported_item.user_reports}") print(f"Mod Reports: {reported_item.mod_reports}")
- spam(*, only: str | None = None, **generator_kwargs: Any) Iterator[praw.models.Comment | praw.models.Submission]
Return a
ListingGenerator
for spam comments and submissions.- Parameters:
only – If specified, one of
"comments"
or"submissions"
to yield only results of that type.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.To print the items in the spam queue try:
for item in reddit.subreddit("mod").mod.spam(): print(item)
- stream() praw.models.reddit.subreddit.SubredditModerationStream
Provide an instance of
SubredditModerationStream
.Streams can be used to indefinitely retrieve Moderator only items from
SubredditModeration
made to moderated subreddits, like:for log in reddit.subreddit("mod").mod.stream.log(): print(f"Mod: {log.mod}, Subreddit: {log.subreddit}")
- unmoderated(**generator_kwargs: Any) Iterator[praw.models.Submission]
Return a
ListingGenerator
for unmoderated submissions.Additional keyword arguments are passed in the initialization of
ListingGenerator
.To print the items in the unmoderated queue try:
for item in reddit.subreddit("mod").mod.unmoderated(): print(item)
- unread(**generator_kwargs: Any) Iterator[praw.models.SubredditMessage]
Return a
ListingGenerator
for unread moderator messages.Warning
Legacy modmail is being deprecated in June 2021. Please see https://www.reddit.com/r/modnews/comments/mar9ha/even_more_modmail_improvements/ for more info.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.See also
inbox()
for all messages.To print the mail in the unread modmail queue try:
for message in reddit.subreddit("mod").mod.unread(): print(f"From: {message.author}, To: {message.dest}")
- update(**settings: str | int | bool) Dict[str, str | int | bool]
Update the
Subreddit
’s settings.- Parameters:
all_original_content – Mandate all submissions to be original content only.
allow_chat_post_creation – Allow users to create chat submissions.
allow_images – Allow users to upload images using the native image hosting.
allow_polls – Allow users to post polls to the subreddit.
allow_post_crossposts – Allow users to crosspost submissions from other subreddits.
allow_top – Allow the subreddit to appear on r/all as well as the default and trending lists.
allow_videos – Allow users to upload videos using the native image hosting.
collapse_deleted_comments – Collapse deleted and removed comments on comments pages by default.
crowd_control_chat_level – Controls the crowd control level for chat rooms. Goes from 0-3.
crowd_control_level – Controls the crowd control level for submissions. Goes from 0-3.
crowd_control_mode – Enables/disables crowd control.
comment_score_hide_mins – The number of minutes to hide comment scores.
description – Shown in the sidebar of your subreddit.
disable_contributor_requests – Specifies whether redditors may send automated modmail messages requesting approval as a submitter.
exclude_banned_modqueue – Exclude posts by site-wide banned users from modqueue/unmoderated.
free_form_reports – Allow users to specify custom reasons in the report menu.
header_hover_text – The text seen when hovering over the snoo.
hide_ads – Don’t show ads within this subreddit. Only applies to Premium-user only subreddits.
key_color – A 6-digit rgb hex color (e.g.,
"#AABBCC"
), used as a thematic color for your subreddit on mobile.lang – A valid IETF language tag (underscore separated).
link_type – The types of submissions users can make. One of
"any"
,"link"
, or"self"
.original_content_tag_enabled – Enables the use of the
original content
label for submissions.over_18 – Viewers must be over 18 years old (i.e., NSFW).
public_description – Public description blurb. Appears in search results and on the landing page for private subreddits.
public_traffic – Make the traffic stats page public.
restrict_commenting – Specifies whether approved users have the ability to comment.
restrict_posting – Specifies whether approved users have the ability to submit posts.
show_media – Show thumbnails on submissions.
show_media_preview – Expand media previews on comments pages.
spam_comments – Spam filter strength for comments. One of
"all"
,"low"
, or"high"
.spam_links – Spam filter strength for links. One of
"all"
,"low"
, or"high"
.spam_selfposts – Spam filter strength for selfposts. One of
"all"
,"low"
, or"high"
.spoilers_enabled – Enable marking posts as containing spoilers.
submit_link_label – Custom label for submit link button (None for default).
submit_text – Text to show on submission page.
submit_text_label – Custom label for submit text post button (None for default).
subreddit_type – The string
"user"
.suggested_comment_sort – All comment threads will use this sorting method by default. Leave
None
, or choose one ofconfidence
,"controversial"
,"live"
,"new"
,"old"
,"qa"
,"random"
, or"top"
.title – The title of the subreddit.
welcome_message_enabled – Enables the subreddit welcome message.
welcome_message_text – The text to be used as a welcome message. A welcome message is sent to all new subscribers by a Reddit bot.
wiki_edit_age – Account age, in days, required to edit and create wiki pages.
wiki_edit_karma – Subreddit karma required to edit and create wiki pages.
wikimode – One of
"anyone"
,"disabled"
, or"modonly"
.
Additional keyword arguments can be provided to handle new settings as Reddit introduces them.
Settings that are documented here and aren’t explicitly set by you in a call to
SubredditModeration.update()
should retain their current value. If they do not please file a bug.Warning
Undocumented settings, or settings that were very recently documented, may not retain their current value when updating. This often occurs when Reddit adds a new setting but forgets to add that setting to the API endpoint that is used to fetch the current settings.
WidgetModeration
- class praw.models.WidgetModeration(widget: praw.models.Widget, subreddit: praw.models.Subreddit | str, reddit: praw.Reddit)
Class for moderating a particular widget.
Example usage:
widget = reddit.subreddit("test").widgets.sidebar[0] widget.mod.update(shortName="My new title") widget.mod.delete()
- __init__(widget: praw.models.Widget, subreddit: praw.models.Subreddit | str, reddit: praw.Reddit)
Initialize a
WidgetModeration
instance.
- delete()
Delete the widget.
Example usage:
widget.mod.delete()
- update(**kwargs) praw.models.ButtonWidget | praw.models.Calendar | praw.models.CommunityList | praw.models.CustomWidget | praw.models.IDCard | praw.models.ImageWidget | praw.models.Menu | praw.models.ModeratorsWidget | praw.models.PostFlairWidget | praw.models.RulesWidget | praw.models.TextArea | praw.models.Widget
Update the widget. Returns the updated widget.
Parameters differ based on the type of widget. See Reddit documentation or the document of the particular type of widget.
- Returns:
The updated
Widget
.
For example, update a text widget like so:
text_widget.mod.update(shortName="New text area", text="Hello!")
Note
Most parameters follow the
lowerCamelCase
convention. When in doubt, check the Reddit documentation linked above.
WikiPageModeration
- class praw.models.reddit.wikipage.WikiPageModeration(wikipage: WikiPage)
Provides a set of moderation functions for a
WikiPage
.For example, to add u/spez as an editor on the wikipage
"praw_test"
try:reddit.subreddit("test").wiki["praw_test"].mod.add("spez")
- __init__(wikipage: WikiPage)
Initialize a
WikiPageModeration
instance.- Parameters:
wikipage – The wikipage to moderate.
- add(redditor: praw.models.Redditor)
Add an editor to this
WikiPage
.- Parameters:
redditor – A redditor name or
Redditor
instance.
To add u/spez as an editor on the wikipage
"praw_test"
try:reddit.subreddit("test").wiki["praw_test"].mod.add("spez")
- remove(redditor: praw.models.Redditor)
Remove an editor from this
WikiPage
.- Parameters:
redditor – A redditor name or
Redditor
instance.
To remove u/spez as an editor on the wikipage
"praw_test"
try:reddit.subreddit("test").wiki["praw_test"].mod.remove("spez")
- revert()
Revert a wikipage back to a specific revision.
To revert the page
"praw_test"
in r/test to revision"1234abc"
, tryreddit.subreddit("test").wiki["praw_test"].revision("1234abc").mod.revert()
Note
When you attempt to revert the page
config/stylesheet
, Reddit checks to see if the revision being reverted to passes the CSS filter. If the check fails, then the revision attempt will also fail, and aprawcore.Forbidden
exception will be raised. For example, you can’t revert to a revision that contains a link tourl(%%PRAW%%)
if there is no image namedPRAW
on the current stylesheet.Here is an example of how to look for this type of error:
from prawcore.exceptions import Forbidden try: reddit.subreddit("test").wiki["config/stylesheet"].revision("1234abc").mod.revert() except Forbidden as exception: try: exception.response.json() except ValueError: exception.response.text
If the error occurs, the output will look something like
{"reason": "INVALID_CSS", "message": "Forbidden", "explanation": "%(css_error)s"}
- update(*, listed: bool, permlevel: int, **other_settings: Any) Dict[str, Any]
Update the settings for this
WikiPage
.- Parameters:
listed – Show this page on page list.
permlevel – Who can edit this page?
0
use subreddit wiki permissions,1
only approved wiki contributors for this page may edit (seeWikiPageModeration.add()
),2
only mods may edit and view.other_settings – Additional keyword arguments to pass.
- Returns:
The updated WikiPage settings.
To set the wikipage
"praw_test"
in r/test to mod only and disable it from showing in the page list, try:reddit.subreddit("test").wiki["praw_test"].mod.update(listed=False, permlevel=2)
LiveContributorRelationship
- class praw.models.reddit.live.LiveContributorRelationship(thread: praw.models.LiveThread)
Provide methods to interact with live threads’ contributors.
- __call__() List[praw.models.Redditor]
Return a
RedditorList
for live threads’ contributors.Usage:
thread = reddit.live("ukaeu1ik4sw5") for contributor in thread.contributor(): print(contributor)
- __init__(thread: praw.models.LiveThread)
Initialize a
LiveContributorRelationship
instance.- Parameters:
thread – An instance of
LiveThread
.
Note
This class should not be initialized directly. Instead, obtain an instance via:
LiveThread.contributor()
.
- accept_invite()
Accept an invite to contribute the live thread.
Usage:
thread = reddit.live("ydwwxneu7vsa") thread.contributor.accept_invite()
- invite(redditor: str | praw.models.Redditor, *, permissions: List[str] | None = None)
Invite a redditor to be a contributor of the live thread.
- Parameters:
redditor – A redditor name or
Redditor
instance.permissions – When provided (not
None
), permissions should be a list of strings specifying which subset of permissions to grant. An empty list[]
indicates no permissions, and when not provided (None
), indicates full permissions.
- Raises:
RedditAPIException
if the invitation already exists.
Usage:
thread = reddit.live("ukaeu1ik4sw5") redditor = reddit.redditor("spez") # "manage" and "settings" permissions thread.contributor.invite(redditor, permissions=["manage", "settings"])
See also
LiveContributorRelationship.remove_invite()
to remove the invite for redditor.
- leave()
Abdicate the live thread contributor position (use with care).
Usage:
thread = reddit.live("ydwwxneu7vsa") thread.contributor.leave()
- remove(redditor: str | praw.models.Redditor)
Remove the redditor from the live thread contributors.
- Parameters:
redditor – A redditor fullname (e.g.,
"t2_1w72"
) orRedditor
instance.
Usage:
thread = reddit.live("ukaeu1ik4sw5") redditor = reddit.redditor("spez") thread.contributor.remove(redditor) thread.contributor.remove("t2_1w72") # with fullname
- remove_invite(redditor: str | praw.models.Redditor)
Remove the invite for redditor.
- Parameters:
redditor – A redditor fullname (e.g.,
"t2_1w72"
) orRedditor
instance.
Usage:
thread = reddit.live("ukaeu1ik4sw5") redditor = reddit.redditor("spez") thread.contributor.remove_invite(redditor) thread.contributor.remove_invite("t2_1w72") # with fullname
See also
LiveContributorRelationship.invite()
to invite a redditor to be a contributor of the live thread.
- update(redditor: str | praw.models.Redditor, *, permissions: List[str] | None = None)
Update the contributor permissions for
redditor
.- Parameters:
redditor – A redditor name or
Redditor
instance.permissions – When provided (not
None
), permissions should be a list of strings specifying which subset of permissions to grant (other permissions are removed). An empty list[]
indicates no permissions, and when not provided (None
), indicates full permissions.
For example, to grant all permissions to the contributor, try:
thread = reddit.live("ukaeu1ik4sw5") thread.contributor.update("spez")
To grant
"access"
and"edit"
permissions (and to remove other permissions), try:thread.contributor.update("spez", permissions=["access", "edit"])
To remove all permissions from the contributor, try:
subreddit.moderator.update("spez", permissions=[])
- update_invite(redditor: str | praw.models.Redditor, *, permissions: List[str] | None = None)
Update the contributor invite permissions for
redditor
.- Parameters:
redditor – A redditor name or
Redditor
instance.permissions – When provided (not
None
), permissions should be a list of strings specifying which subset of permissions to grant (other permissions are removed). An empty list[]
indicates no permissions, and when not provided (None
), indicates full permissions.
For example, to set all permissions to the invitation, try:
thread = reddit.live("ukaeu1ik4sw5") thread.contributor.update_invite("spez")
To set
"access"
and"edit"
permissions (and to remove other permissions) to the invitation, try:thread.contributor.update_invite("spez", permissions=["access", "edit"])
To remove all permissions from the invitation, try:
thread.contributor.update_invite("spez", permissions=[])
LiveThreadContribution
- class praw.models.reddit.live.LiveThreadContribution(thread: praw.models.LiveThread)
Provides a set of contribution functions to a
LiveThread
.- __init__(thread: praw.models.LiveThread)
Initialize a
LiveThreadContribution
instance.- Parameters:
thread – An instance of
LiveThread
.
This instance can be retrieved through
thread.contrib
where thread is aLiveThread
instance. E.g.,thread = reddit.live("ukaeu1ik4sw5") thread.contrib.add("### update")
- add(body: str)
Add an update to the live thread.
- Parameters:
body – The Markdown formatted content for the update.
Usage:
thread = reddit.live("ydwwxneu7vsa") thread.contrib.add("test `LiveThreadContribution.add()`")
- close()
Close the live thread permanently (cannot be undone).
Usage:
thread = reddit.live("ukaeu1ik4sw5") thread.contrib.close()
- update(*, description: str | None = None, nsfw: bool | None = None, resources: str | None = None, title: str | None = None, **other_settings: str | None)
Update settings of the live thread.
- Parameters:
description – The live thread’s description (default:
None
).nsfw – Indicate whether this thread is not safe for work (default:
None
).resources – Markdown formatted information that is useful for the live thread (default:
None
).title – The title of the live thread (default:
None
).
Does nothing if no arguments are provided.
Each setting will maintain its current value if
None
is specified.Additional keyword arguments can be provided to handle new settings as Reddit introduces them.
Usage:
thread = reddit.live("xyu8kmjvfrww") # update 'title' and 'nsfw' updated_thread = thread.contrib.update(title=new_title, nsfw=True)
If Reddit introduces new settings, you must specify
None
for the setting you want to maintain:# update 'nsfw' and maintain new setting 'foo' thread.contrib.update(nsfw=True, foo=None)
LiveThreadStream
- class praw.models.reddit.live.LiveThreadStream(live_thread: praw.models.LiveThread)
Provides a
LiveThread
stream.Usually used via:
for live_update in reddit.live("ta535s1hq2je").stream.updates(): print(live_update.body)
- __init__(live_thread: praw.models.LiveThread)
Initialize a
LiveThreadStream
instance.- Parameters:
live_thread – The live thread associated with the stream.
- updates(**stream_options: Dict[str, Any]) Iterator[praw.models.LiveUpdate]
Yield new updates to the live thread as they become available.
- Parameters:
skip_existing – Set to
True
to only fetch items created after the stream (default:False
).
As with
LiveThread.updates()
, updates are yielded asLiveUpdate
.Updates are yielded oldest first. Up to 100 historical updates will initially be returned.
Keyword arguments are passed to
stream_generator()
.For example, to retrieve all new updates made to the
"ta535s1hq2je"
live thread, try:for live_update in reddit.live("ta535s1hq2je").stream.updates(): print(live_update.body)
To only retrieve new updates starting from when the stream is created, pass
skip_existing=True
:live_thread = reddit.live("ta535s1hq2je") for live_update in live_thread.stream.updates(skip_existing=True): print(live_update.author)
LiveUpdateContribution
- class praw.models.reddit.live.LiveUpdateContribution(update: praw.models.LiveUpdate)
Provides a set of contribution functions to
LiveUpdate
.- __init__(update: praw.models.LiveUpdate)
Initialize a
LiveUpdateContribution
instance.- Parameters:
update – An instance of
LiveUpdate
.
This instance can be retrieved through
update.contrib
where update is aLiveUpdate
instance. E.g.,thread = reddit.live("ukaeu1ik4sw5") update = thread["7827987a-c998-11e4-a0b9-22000b6a88d2"] update.contrib # LiveUpdateContribution instance update.contrib.remove()
- remove()
Remove a live update.
Usage:
thread = reddit.live("ydwwxneu7vsa") update = thread["6854605a-efec-11e6-b0c7-0eafac4ff094"] update.contrib.remove()
- strike()
Strike a content of a live update.
thread = reddit.live("xyu8kmjvfrww") update = thread["cb5fe532-dbee-11e6-9a91-0e6d74fabcc4"] update.contrib.strike()
To check whether the update is stricken or not, use
update.stricken
attribute.Note
Accessing lazy attributes on updates (includes
update.stricken
) may raiseAttributeError
. SeeLiveUpdate
for details.
ContributorRelationship
- class praw.models.reddit.subreddit.ContributorRelationship(subreddit: praw.models.Subreddit, relationship: str)
Provides methods to interact with a
Subreddit
’s contributors.Contributors are also known as approved submitters.
Contributors of a subreddit can be iterated through like so:
for contributor in reddit.subreddit("test").contributor(): print(contributor)
- __call__(redditor: praw.models.Redditor | str | None = None, **generator_kwargs) Iterator[praw.models.Redditor]
Return a
ListingGenerator
forRedditor
s in the relationship.- Parameters:
redditor – When provided, yield at most a single
Redditor
instance. This is useful to confirm if a relationship exists, or to fetch the metadata associated with a particular relationship (default:None
).
Additional keyword arguments are passed in the initialization of
ListingGenerator
.
- __init__(subreddit: praw.models.Subreddit, relationship: str)
Initialize a
SubredditRelationship
instance.- Parameters:
subreddit – The
Subreddit
for the relationship.relationship – The name of the relationship.
- add(redditor: str | praw.models.Redditor, **other_settings: Any)
Add
redditor
to this relationship.- Parameters:
redditor – A redditor name or
Redditor
instance.
- leave()
Abdicate the contributor position.
- remove(redditor: str | praw.models.Redditor)
Remove
redditor
from this relationship.- Parameters:
redditor – A redditor name or
Redditor
instance.
ModeratorRelationship
- class praw.models.reddit.subreddit.ModeratorRelationship(subreddit: praw.models.Subreddit, relationship: str)
Provides methods to interact with a
Subreddit
’s moderators.Moderators of a subreddit can be iterated through like so:
for moderator in reddit.subreddit("test").moderator(): print(moderator)
- __call__(redditor: praw.models.Redditor | str | None = None) List[praw.models.Redditor]
Return a list of
Redditor
s who are moderators.- Parameters:
redditor – When provided, return a list containing at most one
Redditor
instance. This is useful to confirm if a relationship exists, or to fetch the metadata associated with a particular relationship (default:None
).
Note
To help mitigate targeted moderator harassment, this call requires the
Reddit
instance to be authenticated i.e.,read_only
must returnFalse
. This call, however, only makes use of theread
scope. For more information on why the moderator list is hidden can be found here: https://reddit.zendesk.com/hc/en-us/articles/360049499032-Why-is-the-moderator-list-hidden-Note
Unlike other relationship callables, this relationship is not paginated. Thus it simply returns the full list, rather than an iterator for the results.
To be used like:
moderators = reddit.subreddit("test").moderator()
For example, to list the moderators along with their permissions try:
for moderator in reddit.subreddit("test").moderator(): print(f"{moderator}: {moderator.mod_permissions}")
- __init__(subreddit: praw.models.Subreddit, relationship: str)
Initialize a
SubredditRelationship
instance.- Parameters:
subreddit – The
Subreddit
for the relationship.relationship – The name of the relationship.
- add(redditor: str | praw.models.Redditor, *, permissions: List[str] | None = None, **other_settings: Any)
Add or invite
redditor
to be a moderator of theSubreddit
.- Parameters:
redditor – A redditor name or
Redditor
instance.permissions – When provided (not
None
), permissions should be a list of strings specifying which subset of permissions to grant. An empty list[]
indicates no permissions, and when not providedNone
, indicates full permissions (default:None
).
An invite will be sent unless the user making this call is an admin user.
For example, to invite u/spez with
"posts"
and"mail"
permissions to r/test, try:reddit.subreddit("test").moderator.add("spez", permissions=["posts", "mail"])
- invite(redditor: str | praw.models.Redditor, *, permissions: List[str] | None = None, **other_settings: Any)
Invite
redditor
to be a moderator of theSubreddit
.- Parameters:
redditor – A redditor name or
Redditor
instance.permissions – When provided (not
None
), permissions should be a list of strings specifying which subset of permissions to grant. An empty list[]
indicates no permissions, and when not providedNone
, indicates full permissions (default:None
).
For example, to invite u/spez with
"posts"
and"mail"
permissions to r/test, try:reddit.subreddit("test").moderator.invite("spez", permissions=["posts", "mail"])
- invited(*, redditor: praw.models.Redditor | str | None = None, **generator_kwargs: Any) Iterator[praw.models.Redditor]
Return a
ListingGenerator
forRedditor
s invited to be moderators.- Parameters:
redditor – When provided, return a list containing at most one
Redditor
instance. This is useful to confirm if a relationship exists, or to fetch the metadata associated with a particular relationship (default:None
).
Additional keyword arguments are passed in the initialization of
ListingGenerator
.Note
Unlike other usages of
ListingGenerator
,limit
has no effect in the quantity returned. This endpoint always returns moderators in batches of 25 at a time regardless of whatlimit
is set to.Usage:
for invited_mod in reddit.subreddit("test").moderator.invited(): print(invited_mod)
- leave()
Abdicate the moderator position (use with care).
For example:
reddit.subreddit("test").moderator.leave()
- remove(redditor: str | praw.models.Redditor)
Remove
redditor
from this relationship.- Parameters:
redditor – A redditor name or
Redditor
instance.
- remove_invite(redditor: str | praw.models.Redditor)
Remove the moderator invite for
redditor
.- Parameters:
redditor – A redditor name or
Redditor
instance.
For example:
reddit.subreddit("test").moderator.remove_invite("spez")
- update(redditor: str | praw.models.Redditor, *, permissions: List[str] | None = None)
Update the moderator permissions for
redditor
.- Parameters:
redditor – A redditor name or
Redditor
instance.permissions – When provided (not
None
), permissions should be a list of strings specifying which subset of permissions to grant. An empty list[]
indicates no permissions, and when not provided,None
, indicates full permissions (default:None
).
For example, to add all permissions to the moderator, try:
subreddit.moderator.update("spez")
To remove all permissions from the moderator, try:
subreddit.moderator.update("spez", permissions=[])
- update_invite(redditor: str | praw.models.Redditor, *, permissions: List[str] | None = None)
Update the moderator invite permissions for
redditor
.- Parameters:
redditor – A redditor name or
Redditor
instance.permissions – When provided (not
None
), permissions should be a list of strings specifying which subset of permissions to grant. An empty list[]
indicates no permissions, and when not provided,None
, indicates full permissions (default:None
).
For example, to grant the
"flair"
and"mail"
permissions to the moderator invite, try:subreddit.moderator.update_invite("spez", permissions=["flair", "mail"])
SubredditRelationship
- class praw.models.reddit.subreddit.SubredditRelationship(subreddit: praw.models.Subreddit, relationship: str)
Represents a relationship between a
Redditor
andSubreddit
.Instances of this class can be iterated through in order to discover the Redditors that make up the relationship.
For example, banned users of a subreddit can be iterated through like so:
for ban in reddit.subreddit("test").banned(): print(f"{ban}: {ban.note}")
- __call__(redditor: praw.models.Redditor | str | None = None, **generator_kwargs) Iterator[praw.models.Redditor]
Return a
ListingGenerator
forRedditor
s in the relationship.- Parameters:
redditor – When provided, yield at most a single
Redditor
instance. This is useful to confirm if a relationship exists, or to fetch the metadata associated with a particular relationship (default:None
).
Additional keyword arguments are passed in the initialization of
ListingGenerator
.
- __init__(subreddit: praw.models.Subreddit, relationship: str)
Initialize a
SubredditRelationship
instance.- Parameters:
subreddit – The
Subreddit
for the relationship.relationship – The name of the relationship.
- add(redditor: str | praw.models.Redditor, **other_settings: Any)
Add
redditor
to this relationship.- Parameters:
redditor – A redditor name or
Redditor
instance.
- remove(redditor: str | praw.models.Redditor)
Remove
redditor
from this relationship.- Parameters:
redditor – A redditor name or
Redditor
instance.
SubredditEmoji
- class praw.models.reddit.emoji.SubredditEmoji(subreddit: praw.models.Subreddit)
Provides a set of functions to a
Subreddit
for emoji.- __getitem__(name: str) Emoji
Lazily return the
Emoji
for the subreddit namedname
.- Parameters:
name – The name of the emoji.
This method is to be used to fetch a specific emoji url, like so:
emoji = reddit.subreddit("test").emoji["emoji"] print(emoji)
- __init__(subreddit: praw.models.Subreddit)
Initialize a
SubredditEmoji
instance.- Parameters:
subreddit – The subreddit whose emoji are affected.
- __iter__() List[Emoji]
Return a list of
Emoji
for the subreddit.This method is to be used to discover all emoji for a subreddit:
for emoji in reddit.subreddit("test").emoji: print(emoji)
- add(*, image_path: str, mod_flair_only: bool | None = None, name: str, post_flair_allowed: bool | None = None, user_flair_allowed: bool | None = None) Emoji
Add an emoji to this subreddit.
- Parameters:
image_path – A path to a jpeg or png image.
mod_flair_only – When provided, indicate whether the emoji is restricted to mod use only (default:
None
).name – The name of the emoji.
post_flair_allowed – When provided, indicate whether the emoji may appear in post flair (default:
None
).user_flair_allowed – When provided, indicate whether the emoji may appear in user flair (default:
None
).
- Returns:
The
Emoji
added.
To add
"emoji"
to r/test try:reddit.subreddit("test").emoji.add(name="emoji", image_path="emoji.png")
SubredditFilters
- class praw.models.reddit.subreddit.SubredditFilters(subreddit: praw.models.Subreddit)
Provide functions to interact with the special
Subreddit
’s filters.Members of this class should be utilized via
Subreddit.filters()
. For example, to add a filter, run:reddit.subreddit("all").filters.add("test")
- __init__(subreddit: praw.models.Subreddit)
Initialize a
SubredditFilters
instance.- Parameters:
subreddit – The special subreddit whose filters to work with.
As of this writing filters can only be used with the special subreddits
all
andmod
.
- __iter__() Generator[praw.models.Subreddit, None, None]
Iterate through the special
Subreddit
’s filters.This method should be invoked as:
for subreddit in reddit.subreddit("test").filters: ...
- add(subreddit: praw.models.Subreddit | str)
Add
subreddit
to the list of filtered subreddits.- Parameters:
subreddit – The subreddit to add to the filter list.
Items from subreddits added to the filtered list will no longer be included when obtaining listings for r/all.
Alternatively, you can filter a subreddit temporarily from a special listing in a manner like so:
reddit.subreddit("all-redditdev-learnpython")
- Raises:
prawcore.NotFound
when calling on a non-special subreddit.
- remove(subreddit: praw.models.Subreddit | str)
Remove
subreddit
from the list of filtered subreddits.- Parameters:
subreddit – The subreddit to remove from the filter list.
- Raises:
prawcore.NotFound
when calling on a non-special subreddit.
SubredditModerationStream
- class praw.models.reddit.subreddit.SubredditModerationStream(subreddit: praw.models.Subreddit)
Provides moderator streams.
- __init__(subreddit: praw.models.Subreddit)
Initialize a
SubredditModerationStream
instance.- Parameters:
subreddit – The moderated subreddit associated with the streams.
- edited(*, only: str | None = None, **stream_options: Any) Generator[praw.models.Comment | praw.models.Submission, None, None]
Yield edited comments and submissions as they become available.
- Parameters:
only – If specified, one of
"comments"
or"submissions"
to yield only results of that type.
Keyword arguments are passed to
stream_generator()
.For example, to retrieve all new edited submissions/comments made to all moderated subreddits, try:
for item in reddit.subreddit("mod").mod.stream.edited(): print(item)
- log(*, action: str | None = None, mod: praw.models.Redditor | str | None = None, **stream_options: Any) Generator[praw.models.ModAction, None, None]
Yield moderator log entries as they become available.
- Parameters:
action – If given, only return log entries for the specified action.
mod – If given, only return log entries for actions made by the passed in redditor.
For example, to retrieve all new mod actions made to all moderated subreddits, try:
for log in reddit.subreddit("mod").mod.stream.log(): print(f"Mod: {log.mod}, Subreddit: {log.subreddit}")
- modmail_conversations(*, other_subreddits: List[praw.models.Subreddit] | None = None, sort: str | None = None, state: str | None = None, **stream_options: Any) Generator[ModmailConversation, None, None]
Yield new-modmail conversations as they become available.
- Parameters:
other_subreddits – A list of
Subreddit
instances for which to fetch conversations (default:None
).sort – Can be one of:
"mod"
,"recent"
,"unread"
, or"user"
(default:"recent"
).state – Can be one of:
"all"
,"appeals"
,"archived"
,"default"
,"highlighted"
,"inbox"
,"inprogress"
,"join_requests"
,"mod"
,"new"
, or"notifications"
(default:"all"
)."all"
does not include mod or archived conversations."inbox"
does not include appeals conversations.
Keyword arguments are passed to
stream_generator()
.To print new mail in the unread modmail queue try:
subreddit = reddit.subreddit("all") for message in subreddit.mod.stream.modmail_conversations(): print(f"From: {message.owner}, To: {message.participant}")
- modqueue(*, only: str | None = None, **stream_options: Any) Generator[praw.models.Comment | praw.models.Submission, None, None]
Yield
Comment
s andSubmission
s in the modqueue as they become available.- Parameters:
only – If specified, one of
"comments"
or"submissions"
to yield only results of that type.
Keyword arguments are passed to
stream_generator()
.To print all new modqueue items try:
for item in reddit.subreddit("mod").mod.stream.modqueue(): print(item)
- reports(*, only: str | None = None, **stream_options: Any) Generator[praw.models.Comment | praw.models.Submission, None, None]
Yield reported
Comment
s andSubmission
s as they become available.- Parameters:
only – If specified, one of
"comments"
or"submissions"
to yield only results of that type.
Keyword arguments are passed to
stream_generator()
.To print new user and mod report reasons in the report queue try:
for item in reddit.subreddit("mod").mod.stream.reports(): print(item)
- spam(*, only: str | None = None, **stream_options: Any) Generator[praw.models.Comment | praw.models.Submission, None, None]
Yield spam
Comment
s andSubmission
s as they become available.- Parameters:
only – If specified, one of
"comments"
or"submissions"
to yield only results of that type.
Keyword arguments are passed to
stream_generator()
.To print new items in the spam queue try:
for item in reddit.subreddit("mod").mod.stream.spam(): print(item)
- unmoderated(**stream_options: Any) Generator[praw.models.Submission, None, None]
Yield unmoderated
Submission
s as they become available.Keyword arguments are passed to
stream_generator()
.To print new items in the unmoderated queue try:
for item in reddit.subreddit("mod").mod.stream.unmoderated(): print(item)
- unread(**stream_options: Any) Generator[praw.models.SubredditMessage, None, None]
Yield unread old modmail messages as they become available.
Keyword arguments are passed to
stream_generator()
.See also
SubredditModeration.inbox()
for all messages.To print new mail in the unread modmail queue try:
for message in reddit.subreddit("mod").mod.stream.unread(): print(f"From: {message.author}, To: {message.dest}")
SubredditQuarantine
- class praw.models.reddit.subreddit.SubredditQuarantine(subreddit: praw.models.Subreddit)
Provides subreddit quarantine related methods.
To opt-in into a quarantined subreddit:
reddit.subreddit("test").quaran.opt_in()
- __init__(subreddit: praw.models.Subreddit)
Initialize a
SubredditQuarantine
instance.- Parameters:
subreddit – The
Subreddit
associated with the quarantine.
- opt_in()
Permit your user access to the quarantined subreddit.
Usage:
subreddit = reddit.subreddit("QUESTIONABLE") next(subreddit.hot()) # Raises prawcore.Forbidden subreddit.quaran.opt_in() next(subreddit.hot()) # Returns Submission
- opt_out()
Remove access to the quarantined subreddit.
Usage:
subreddit = reddit.subreddit("QUESTIONABLE") next(subreddit.hot()) # Returns Submission subreddit.quaran.opt_out() next(subreddit.hot()) # Raises prawcore.Forbidden
SubredditRemovalReasons
- class praw.models.reddit.removal_reasons.SubredditRemovalReasons(subreddit: praw.models.Subreddit)
Provide a set of functions to a
Subreddit
’s removal reasons.- __getitem__(reason_id: str | int | slice) RemovalReason
Return the Removal Reason with the ID/number/slice
reason_id
.- Parameters:
reason_id – The ID or index of the removal reason
Note
Removal reasons fetched using a specific rule name are lazily loaded, so you might have to access an attribute to get all the expected attributes.
This method is to be used to fetch a specific removal reason, like so:
reason_id = "141vv5c16py7d" reason = reddit.subreddit("test").mod.removal_reasons[reason_id] print(reason)
You can also use indices to get a numbered removal reason. Since Python uses 0-indexing, the first removal reason is index 0, and so on.
Note
Both negative indices and slices can be used to interact with the removal reasons.
- Raises:
IndexError
if a removal reason of a specific number does not exist.
For example, to get the second removal reason of r/test:
reason = reddit.subreddit("test").mod.removal_reasons[1]
To get the last three removal reasons in a subreddit:
reasons = reddit.subreddit("test").mod.removal_reasons[-3:] for reason in reasons: print(reason)
- __init__(subreddit: praw.models.Subreddit)
Initialize a
SubredditRemovalReasons
instance.- Parameters:
subreddit – The subreddit whose removal reasons to work with.
- __iter__() Iterator[RemovalReason]
Return a list of Removal Reasons for the subreddit.
This method is used to discover all removal reasons for a subreddit:
for removal_reason in reddit.subreddit("test").mod.removal_reasons: print(removal_reason)
- add(*, message: str, title: str) RemovalReason
Add a removal reason to this subreddit.
- Parameters:
message – The message associated with the removal reason.
title – The title of the removal reason.
- Returns:
The
RemovalReason
added.
The message will be prepended with
Hi u/username,
automatically.To add
"Test"
to r/test try:reddit.subreddit("test").mod.removal_reasons.add(title="Test", message="Foobar")
SubredditRules
- class praw.models.reddit.rules.SubredditRules(subreddit: praw.models.Subreddit)
Provide a set of functions to access a
Subreddit
’s rules.For example, to list all the rules for a subreddit:
for rule in reddit.subreddit("test").rules: print(rule)
Moderators can also add rules to the subreddit. For example, to make a rule called
"No spam"
in r/test:reddit.subreddit("test").rules.mod.add( short_name="No spam", kind="all", description="Do not spam. Spam bad" )
- __call__() List[praw.models.Rule]
Return a list of
Rule
s (Deprecated).- Returns:
A list of instances of
Rule
.
Deprecated since version 7.1: Use the iterator by removing the call to
SubredditRules
. For example, in order to use the iterator:for rule in reddit.subreddit("test").rules: print(rule)
- __getitem__(short_name: str | int | slice) praw.models.Rule
Return the
Rule
for the subreddit with short_nameshort_name
.- Parameters:
short_name – The short_name of the rule, or the rule number.
Note
Rules fetched using a specific rule name are lazily loaded, so you might have to access an attribute to get all the expected attributes.
This method is to be used to fetch a specific rule, like so:
rule_name = "No spam" rule = reddit.subreddit("test").rules[rule_name] print(rule)
You can also fetch a numbered rule of a subreddit.
Rule numbers start at
0
, so the first rule is at index0
, and the second rule is at index1
, and so on.- Raises:
IndexError
if a rule of a specific number does not exist.
Note
You can use negative indexes, such as
-1
, to get the last rule. You can also use slices, to get a subset of rules, such as the last three rules withrules[-3:]
.For example, to fetch the second rule of r/test:
rule = reddit.subreddit("test").rules[1]
- __init__(subreddit: praw.models.Subreddit)
Initialize a
SubredditRules
instance.- Parameters:
subreddit – The subreddit whose rules to work with.
- __iter__() Iterator[praw.models.Rule]
Iterate through the rules of the subreddit.
- Returns:
An iterator containing all the rules of a subreddit.
This method is used to discover all rules for a subreddit.
For example, to get the rules for r/test:
for rule in reddit.subreddit("test").rules: print(rule)
- mod() SubredditRulesModeration
Contain methods to moderate subreddit rules as a whole.
To add rule
"No spam"
to r/test try:reddit.subreddit("test").rules.mod.add( short_name="No spam", kind="all", description="Do not spam. Spam bad" )
To move the fourth rule to the first position, and then to move the prior first rule to where the third rule originally was in r/test:
subreddit = reddit.subreddit("test") rules = list(subreddit.rules) new_rules = rules[3:4] + rules[1:3] + rules[0:1] + rules[4:] # Alternate: [rules[3]] + rules[1:3] + [rules[0]] + rules[4:] new_rule_list = subreddit.rules.mod.reorder(new_rules)
SubredditStream
- class praw.models.reddit.subreddit.SubredditStream(subreddit: praw.models.Subreddit)
Provides submission and comment streams.
- __init__(subreddit: praw.models.Subreddit)
Initialize a
SubredditStream
instance.- Parameters:
subreddit – The subreddit associated with the streams.
- comments(**stream_options: Any) Generator[praw.models.Comment, None, None]
Yield new comments as they become available.
Comments are yielded oldest first. Up to 100 historical comments will initially be returned.
Keyword arguments are passed to
stream_generator()
.Note
While PRAW tries to catch all new comments, some high-volume streams, especially the r/all stream, may drop some comments.
For example, to retrieve all new comments made to r/test, try:
for comment in reddit.subreddit("test").stream.comments(): print(comment)
To only retrieve new submissions starting when the stream is created, pass
skip_existing=True
:subreddit = reddit.subreddit("test") for comment in subreddit.stream.comments(skip_existing=True): print(comment)
- submissions(**stream_options: Any) Generator[praw.models.Submission, None, None]
Yield new
Submission
s as they become available.Submissions are yielded oldest first. Up to 100 historical submissions will initially be returned.
Keyword arguments are passed to
stream_generator()
.Note
While PRAW tries to catch all new submissions, some high-volume streams, especially the r/all stream, may drop some submissions.
For example, to retrieve all new submissions made to all of Reddit, try:
for submission in reddit.subreddit("all").stream.submissions(): print(submission)
SubredditStylesheet
- class praw.models.reddit.subreddit.SubredditStylesheet(subreddit: praw.models.Subreddit)
Provides a set of stylesheet functions to a
Subreddit
.For example, to add the css data
.test{color:blue}
to the existing stylesheet:subreddit = reddit.subreddit("test") stylesheet = subreddit.stylesheet() stylesheet.stylesheet += ".test{color:blue}" subreddit.stylesheet.update(stylesheet.stylesheet)
- __call__() praw.models.Stylesheet
Return the
Subreddit
’s stylesheet.To be used as:
stylesheet = reddit.subreddit("test").stylesheet()
- __init__(subreddit: praw.models.Subreddit)
Initialize a
SubredditStylesheet
instance.- Parameters:
subreddit – The
Subreddit
associated with the stylesheet.
An instance of this class is provided as:
reddit.subreddit("test").stylesheet
- delete_banner()
Remove the current
Subreddit
(redesign) banner image.Succeeds even if there is no banner image.
For example:
reddit.subreddit("test").stylesheet.delete_banner()
- delete_banner_additional_image()
Remove the current
Subreddit
(redesign) banner additional image.Succeeds even if there is no additional image. Will also delete any configured hover image.
For example:
reddit.subreddit("test").stylesheet.delete_banner_additional_image()
- delete_banner_hover_image()
Remove the current
Subreddit
(redesign) banner hover image.Succeeds even if there is no hover image.
For example:
reddit.subreddit("test").stylesheet.delete_banner_hover_image()
- delete_header()
Remove the current
Subreddit
header image.Succeeds even if there is no header image.
For example:
reddit.subreddit("test").stylesheet.delete_header()
- delete_image(name: str)
Remove the named image from the
Subreddit
.Succeeds even if the named image does not exist.
For example:
reddit.subreddit("test").stylesheet.delete_image("smile")
- delete_mobile_banner()
Remove the current
Subreddit
(redesign) mobile banner.Succeeds even if there is no mobile banner.
For example:
subreddit = reddit.subreddit("test") subreddit.stylesheet.delete_banner_hover_image()
- delete_mobile_header()
Remove the current
Subreddit
mobile header.Succeeds even if there is no mobile header.
For example:
reddit.subreddit("test").stylesheet.delete_mobile_header()
- delete_mobile_icon()
Remove the current
Subreddit
mobile icon.Succeeds even if there is no mobile icon.
For example:
reddit.subreddit("test").stylesheet.delete_mobile_icon()
- update(stylesheet: str, *, reason: str | None = None)
Update the
Subreddit
’s stylesheet.- Parameters:
stylesheet – The CSS for the new stylesheet.
reason – The reason for updating the stylesheet.
For example:
reddit.subreddit("test").stylesheet.update( "p { color: green; }", reason="color text green" )
- upload(*, image_path: str, name: str) Dict[str, str]
Upload an image to the
Subreddit
.- Parameters:
image_path – A path to a jpeg or png image.
name – The name to use for the image. If an image already exists with the same name, it will be replaced.
- Returns:
A dictionary containing a link to the uploaded image under the key
img_src
.- Raises:
prawcore.TooLarge
if the overall request body is too large.- Raises:
RedditAPIException
if there are other issues with the uploaded image. Unfortunately the exception info might not be very specific, so try through the website with the same image to see what the problem actually might be.
For example:
reddit.subreddit("test").stylesheet.upload(name="smile", image_path="img.png")
- upload_banner(image_path: str)
Upload an image for the
Subreddit
’s (redesign) banner image.- Parameters:
image_path – A path to a jpeg or png image.
- Raises:
prawcore.TooLarge
if the overall request body is too large.- Raises:
RedditAPIException
if there are other issues with the uploaded image. Unfortunately the exception info might not be very specific, so try through the website with the same image to see what the problem actually might be.
For example:
reddit.subreddit("test").stylesheet.upload_banner("banner.png")
- upload_banner_additional_image(image_path: str, *, align: str | None = None)
Upload an image for the
Subreddit
’s (redesign) additional image.- Parameters:
image_path – A path to a jpeg or png image.
align – Either
"left"
,"centered"
, or"right"
. (default:"left"
).
- Raises:
prawcore.TooLarge
if the overall request body is too large.- Raises:
RedditAPIException
if there are other issues with the uploaded image. Unfortunately the exception info might not be very specific, so try through the website with the same image to see what the problem actually might be.
For example:
subreddit = reddit.subreddit("test") subreddit.stylesheet.upload_banner_additional_image("banner.png")
- upload_banner_hover_image(image_path: str)
Upload an image for the
Subreddit
’s (redesign) additional image.- Parameters:
image_path – A path to a jpeg or png image.
Fails if the
Subreddit
does not have an additional image defined.- Raises:
prawcore.TooLarge
if the overall request body is too large.- Raises:
RedditAPIException
if there are other issues with the uploaded image. Unfortunately the exception info might not be very specific, so try through the website with the same image to see what the problem actually might be.
For example:
subreddit = reddit.subreddit("test") subreddit.stylesheet.upload_banner_hover_image("banner.png")
- upload_header(image_path: str) Dict[str, str]
Upload an image to be used as the
Subreddit
’s header image.- Parameters:
image_path – A path to a jpeg or png image.
- Returns:
A dictionary containing a link to the uploaded image under the key
img_src
.- Raises:
prawcore.TooLarge
if the overall request body is too large.- Raises:
RedditAPIException
if there are other issues with the uploaded image. Unfortunately the exception info might not be very specific, so try through the website with the same image to see what the problem actually might be.
For example:
reddit.subreddit("test").stylesheet.upload_header("header.png")
- upload_mobile_banner(image_path: str)
Upload an image for the
Subreddit
’s (redesign) mobile banner.- Parameters:
image_path – A path to a JPEG or PNG image.
For example:
subreddit = reddit.subreddit("test") subreddit.stylesheet.upload_mobile_banner("banner.png")
Fails if the
Subreddit
does not have an additional image defined.- Raises:
prawcore.TooLarge
if the overall request body is too large.- Raises:
RedditAPIException
if there are other issues with the uploaded image. Unfortunately the exception info might not be very specific, so try through the website with the same image to see what the problem actually might be.
- upload_mobile_header(image_path: str) Dict[str, str]
Upload an image to be used as the
Subreddit
’s mobile header.- Parameters:
image_path – A path to a jpeg or png image.
- Returns:
A dictionary containing a link to the uploaded image under the key
img_src
.- Raises:
prawcore.TooLarge
if the overall request body is too large.- Raises:
RedditAPIException
if there are other issues with the uploaded image. Unfortunately the exception info might not be very specific, so try through the website with the same image to see what the problem actually might be.
For example:
reddit.subreddit("test").stylesheet.upload_mobile_header("header.png")
- upload_mobile_icon(image_path: str) Dict[str, str]
Upload an image to be used as the
Subreddit
’s mobile icon.- Parameters:
image_path – A path to a jpeg or png image.
- Returns:
A dictionary containing a link to the uploaded image under the key
img_src
.- Raises:
prawcore.TooLarge
if the overall request body is too large.- Raises:
RedditAPIException
if there are other issues with the uploaded image. Unfortunately the exception info might not be very specific, so try through the website with the same image to see what the problem actually might be.
For example:
reddit.subreddit("test").stylesheet.upload_mobile_icon("icon.png")
SubredditWidgets
- class praw.models.SubredditWidgets(subreddit: praw.models.Subreddit)
Class to represent a
Subreddit
’s widgets.Create an instance like so:
widgets = reddit.subreddit("test").widgets
Data will be lazy-loaded. By default, PRAW will not request progressively loading images from Reddit. To enable this, instantiate a
SubredditWidgets
object viawidgets()
, then set the attributeprogressive_images
toTrue
before performing any action that would result in a network request.widgets = reddit.subreddit("test").widgets widgets.progressive_images = True for widget in widgets.sidebar: # do something ...
Access a
Subreddit
’s widgets with the following attributes:print(widgets.id_card) print(widgets.moderators_widget) print(widgets.sidebar) print(widgets.topbar)
The attribute
id_card
contains theSubreddit
’s ID card, which displays information like the number of subscribers.The attribute
moderators_widget
contains theSubreddit
’s moderators widget, which lists the moderators of the subreddit.The attribute
sidebar
contains a list of widgets which make up the sidebar of the subreddit.The attribute
topbar
contains a list of widgets which make up the top bar of the subreddit.To edit a
Subreddit
’s widgets, usemod
. For example:widgets.mod.add_text_area( short_name="My title", text="**bold text**", styles={"backgroundColor": "#FFFF66", "headerColor": "#3333EE"}, )
For more information, see
SubredditWidgetsModeration
.To edit a particular widget, use
.mod
on the widget. For example:for widget in widgets.sidebar: widget.mod.update(shortName="Exciting new name")
For more information, see
WidgetModeration
.Currently available widgets:
- __init__(subreddit: praw.models.Subreddit)
Initialize a
SubredditWidgets
instance.- Parameters:
subreddit – The
Subreddit
the widgets belong to.
- id_card() praw.models.IDCard
- items() Dict[str, praw.models.Widget]
Get this
Subreddit
’s widgets as a dict from ID to widget.
- mod() praw.models.SubredditWidgetsModeration
Get an instance of
SubredditWidgetsModeration
.Note
Using any of the methods of
SubredditWidgetsModeration
will likely result in the data of thisSubredditWidgets
being outdated. To re-sync, callrefresh()
.
- moderators_widget() praw.models.ModeratorsWidget
Get this
Subreddit
’sModeratorsWidget
.
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit) Any
Return an instance of
cls
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.
- refresh()
Refresh the
Subreddit
’s widgets.By default, PRAW will not request progressively loading images from Reddit. To enable this, set the attribute
progressive_images
toTrue
prior to callingrefresh()
.widgets = reddit.subreddit("test").widgets widgets.progressive_images = True widgets.refresh()
- sidebar() List[praw.models.Widget]
Get a list of
Widget
s that make up the sidebar.
- topbar() List[praw.models.Menu]
Get a list of
Widget
s that make up the top bar.
SubredditWiki
- class praw.models.reddit.subreddit.SubredditWiki(subreddit: praw.models.Subreddit)
Provides a set of wiki functions to a
Subreddit
.- __getitem__(page_name: str) WikiPage
Lazily return the
WikiPage
for theSubreddit
namedpage_name
.This method is to be used to fetch a specific wikipage, like so:
wikipage = reddit.subreddit("test").wiki["proof"] print(wikipage.content_md)
- __init__(subreddit: praw.models.Subreddit)
Initialize a
SubredditWiki
instance.- Parameters:
subreddit – The subreddit whose wiki to work with.
- __iter__() Generator[WikiPage, None, None]
Iterate through the pages of the wiki.
This method is to be used to discover all wikipages for a subreddit:
for wikipage in reddit.subreddit("test").wiki: print(wikipage)
- create(*, content: str, name: str, reason: str | None = None, **other_settings: Any)
Create a new
WikiPage
.- Parameters:
To create the wiki page
"praw_test"
in r/test try:reddit.subreddit("test").wiki.create( name="praw_test", content="wiki body text", reason="PRAW Test Creation" )
- revisions(**generator_kwargs: Any) Generator[Dict[str, praw.models.Redditor | WikiPage | str | int | bool | None], None, None]
Return a
ListingGenerator
for recent wiki revisions.Additional keyword arguments are passed in the initialization of
ListingGenerator
.To view the wiki revisions for
"praw_test"
in r/test try:for item in reddit.subreddit("test").wiki["praw_test"].revisions(): print(item)
Calendar
- class praw.models.Calendar(reddit: praw.Reddit, _data: Dict[str, Any])
Class to represent a calendar widget.
Find an existing one:
calendar = None widgets = reddit.subreddit("test").widgets for widget in widgets.sidebar: if isinstance(widget, praw.models.Calendar): calendar = widget break print(calendar.googleCalendarId)
Create one:
widgets = reddit.subreddit("test").widgets styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} config = { "numEvents": 10, "showDate": True, "showDescription": False, "showLocation": False, "showTime": True, "showTitle": True, } cal_id = "y6nm89jy427drk8l71w75w9wjn@group.calendar.google.com" calendar = widgets.mod.add_calendar( short_name="Upcoming Events", google_calendar_id=cal_id, requires_sync=True, configuration=config, styles=styles, )
For more information on creation, see
add_calendar()
.Update one:
new_styles = {"backgroundColor": "#FFFFFF", "headerColor": "#FF9900"} calendar = calendar.mod.update(shortName="My fav events", styles=new_styles)
Delete one:
calendar.mod.delete()
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
configuration
A
dict
describing the calendar configuration.data
A list of dictionaries that represent events.
id
The widget ID.
kind
The widget kind (always
"calendar"
).requiresSync
A
bool
representing whether the calendar requires synchronization.shortName
The short name of the widget.
styles
A
dict
with the keys"backgroundColor"
and"headerColor"
.subreddit
The
Subreddit
the button widget belongs to.- mod() praw.models.WidgetModeration
Get an instance of
WidgetModeration
for this widget.Note
Using any of the methods of
WidgetModeration
will likely make the data in theSubredditWidgets
that this widget belongs to outdated. To remedy this, callrefresh()
.
CalendarConfiguration
- class praw.models.CalendarConfiguration(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Class to represent the configuration of a
Calendar
.Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
numEvents
The number of events to display on the calendar.
showDate
Whether to show the dates of events.
showDescription
Whether to show the descriptions of events.
showLocation
Whether to show the locations of events.
showTime
Whether to show the times of events.
showTitle
Whether to show the titles of events.
CommunityList
- class praw.models.CommunityList(reddit: praw.Reddit, _data: Dict[str, Any])
Class to represent a Related Communities widget.
Find an existing one:
community_list = None widgets = reddit.subreddit("test").widgets for widget in widgets.sidebar: if isinstance(widget, praw.models.CommunityList): community_list = widget break print(community_list)
Create one:
widgets = reddit.subreddit("test").widgets styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} subreddits = ["learnpython", reddit.subreddit("test")] community_list = widgets.mod.add_community_list( short_name="Related subreddits", data=subreddits, styles=styles, description="description", )
For more information on creation, see
add_community_list()
.Update one:
new_styles = {"backgroundColor": "#FFFFFF", "headerColor": "#FF9900"} community_list = community_list.mod.update(shortName="My fav subs", styles=new_styles)
Delete one:
community_list.mod.delete()
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
data
A list of
Subreddit
s. These can also be iterated over by iterating over theCommunityList
(e.g.,for sub in community_list
).id
The widget ID.
kind
The widget kind (always
"community-list"
).shortName
The short name of the widget.
styles
A
dict
with the keys"backgroundColor"
and"headerColor"
.subreddit
The
Subreddit
the button widget belongs to.- mod() praw.models.WidgetModeration
Get an instance of
WidgetModeration
for this widget.Note
Using any of the methods of
WidgetModeration
will likely make the data in theSubredditWidgets
that this widget belongs to outdated. To remedy this, callrefresh()
.
CustomWidget
- class praw.models.CustomWidget(reddit: praw.Reddit, _data: Dict[str, Any])
Class to represent a custom widget.
Find an existing one:
custom = None widgets = reddit.subreddit("test").widgets for widget in widgets.sidebar: if isinstance(widget, praw.models.CustomWidget): custom = widget break print(custom.text) print(custom.css)
Create one:
widgets = reddit.subreddit("test").widgets styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} custom = widgets.mod.add_custom_widget( short_name="My custom widget", text="# Hello world!", css="/**/", height=200, image_data=[], styles=styles, )
For more information on creation, see
add_custom_widget()
.Update one:
new_styles = {"backgroundColor": "#FFFFFF", "headerColor": "#FF9900"} custom = custom.mod.update(shortName="My fav customization", styles=new_styles)
Delete one:
custom.mod.delete()
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
css
The CSS of the widget, as a
str
.height
The height of the widget, as an
int
.id
The widget ID.
imageData
A
list
ofImageData
that belong to the widget.kind
The widget kind (always
"custom"
).shortName
The short name of the widget.
styles
A
dict
with the keys"backgroundColor"
and"headerColor"
.stylesheetUrl
A link to the widget’s stylesheet.
subreddit
The
Subreddit
the button widget belongs to.text
The text contents, as Markdown.
textHtml
The text contents, as HTML.
- __init__(reddit: praw.Reddit, _data: Dict[str, Any])
Initialize a
CustomWidget
instance.
- mod() praw.models.WidgetModeration
Get an instance of
WidgetModeration
for this widget.Note
Using any of the methods of
WidgetModeration
will likely make the data in theSubredditWidgets
that this widget belongs to outdated. To remedy this, callrefresh()
.
Hover
- class praw.models.Hover(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Class to represent the hover data for a
ButtonWidget
.These values will take effect when the button is hovered over (the user moves their cursor so it’s on top of the button).
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
color
The hex color used to outline the button.
fillColor
The hex color for the background of the button.
textColor
The hex color for the text of the button.
height
Image height. Only present on image buttons.
kind
Either
text
orimage
.text
The text displayed on the button.
url
If the button is a text button, a link that can be visited by clicking the button.
If the button is an image button, the URL of a Reddit-hosted image.
width
Image width. Only present on image buttons.
IDCard
- class praw.models.IDCard(reddit: praw.Reddit, _data: Dict[str, Any])
Class to represent an ID card widget.
widgets = reddit.subreddit("test").widgets id_card = widgets.id_card print(id_card.subscribersText)
Update one:
widgets.id_card.mod.update(currentlyViewingText="Bots")
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
currentlyViewingCount
The number of redditors viewing the subreddit.
currentlyViewingText
The text displayed next to the view count. For example,
"users online"
.description
The subreddit description.
id
The widget ID.
kind
The widget kind (always
"id-card"
).shortName
The short name of the widget.
styles
A
dict
with the keys"backgroundColor"
and"headerColor"
.subreddit
The
Subreddit
the button widget belongs to.subscribersCount
The number of subscribers to the subreddit.
subscribersText
The text displayed next to the subscriber count. For example, “users subscribed”.
- mod() praw.models.WidgetModeration
Get an instance of
WidgetModeration
for this widget.Note
Using any of the methods of
WidgetModeration
will likely make the data in theSubredditWidgets
that this widget belongs to outdated. To remedy this, callrefresh()
.
Image
- class praw.models.Image(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Class to represent an image that’s part of a
ImageWidget
.Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
height
Image height.
linkUrl
A link that can be visited by clicking the image.
url
The URL of the (Reddit-hosted) image.
width
Image width.
ImageData
- class praw.models.ImageData(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Class for image data that’s part of a
CustomWidget
.Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
height
The image height.
name
The image name.
url
The URL of the image on Reddit’s servers.
width
The image width.
ImageWidget
- class praw.models.ImageWidget(reddit: praw.Reddit, _data: Dict[str, Any])
Class to represent an image widget.
Find an existing one:
image_widget = None widgets = reddit.subreddit("test").widgets for widget in widgets.sidebar: if isinstance(widget, praw.models.ImageWidget): image_widget = widget break for image in image_widget: print(image.url)
Create one:
widgets = reddit.subreddit("test").widgets image_paths = ["/path/to/image1.jpg", "/path/to/image2.png"] image_data = [ { "width": 600, "height": 450, "linkUrl": "", "url": widgets.mod.upload_image(img_path), } for img_path in image_paths ] styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} image_widget = widgets.mod.add_image_widget( short_name="My cool pictures", data=image_data, styles=styles )
For more information on creation, see
add_image_widget()
.Update one:
new_styles = {"backgroundColor": "#FFFFFF", "headerColor": "#FF9900"} image_widget = image_widget.mod.update(shortName="My fav images", styles=new_styles)
Delete one:
image_widget.mod.delete()
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
data
A list of the
Image
s in this widget. Can be iterated over by iterating over theImageWidget
(e.g.,for img in image_widget
).id
The widget ID.
kind
The widget kind (always
"image"
).shortName
The short name of the widget.
styles
A
dict
with the keys"backgroundColor"
and"headerColor"
.subreddit
The
Subreddit
the button widget belongs to.- mod() praw.models.WidgetModeration
Get an instance of
WidgetModeration
for this widget.Note
Using any of the methods of
WidgetModeration
will likely make the data in theSubredditWidgets
that this widget belongs to outdated. To remedy this, callrefresh()
.
ModeratorsWidget
- class praw.models.ModeratorsWidget(reddit: praw.Reddit, _data: Dict[str, Any])
Class to represent a moderators widget.
widgets = reddit.subreddit("test").widgets print(widgets.moderators_widget)
Update one:
new_styles = {"backgroundColor": "#FFFFFF", "headerColor": "#FF9900"} widgets.moderators_widget.mod.update(styles=new_styles)
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
id
The widget ID.
kind
The widget kind (always
"moderators"
).mods
A list of the
Redditor
s that moderate the subreddit. Can be iterated over by iterating over theModeratorsWidget
(e.g.,for mod in widgets.moderators_widget
).styles
A
dict
with the keys"backgroundColor"
and"headerColor"
.subreddit
The
Subreddit
the button widget belongs to.totalMods
The total number of moderators in the subreddit.
- __init__(reddit: praw.Reddit, _data: Dict[str, Any])
Initialize a
ModeratorsWidget
instance.
- mod() praw.models.WidgetModeration
Get an instance of
WidgetModeration
for this widget.Note
Using any of the methods of
WidgetModeration
will likely make the data in theSubredditWidgets
that this widget belongs to outdated. To remedy this, callrefresh()
.
PostFlairWidget
- class praw.models.PostFlairWidget(reddit: praw.Reddit, _data: Dict[str, Any])
Class to represent a post flair widget.
Find an existing one:
post_flair_widget = None widgets = reddit.subreddit("test").widgets for widget in widgets.sidebar: if isinstance(widget, praw.models.PostFlairWidget): post_flair_widget = widget break for flair in post_flair_widget: print(flair) print(post_flair_widget.templates[flair])
Create one:
subreddit = reddit.subreddit("test") widgets = subreddit.widgets flairs = [f["id"] for f in subreddit.flair.link_templates] styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} post_flair = widgets.mod.add_post_flair_widget( short_name="Some flairs", display="list", order=flairs, styles=styles )
For more information on creation, see
add_post_flair_widget()
.Update one:
new_styles = {"backgroundColor": "#FFFFFF", "headerColor": "#FF9900"} post_flair = post_flair.mod.update(shortName="My fav flairs", styles=new_styles)
Delete one:
post_flair.mod.delete()
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
display
The display style of the widget, either
"cloud"
or"list"
.id
The widget ID.
kind
The widget kind (always
"post-flair"
).order
A list of the flair IDs in this widget. Can be iterated over by iterating over the
PostFlairWidget
(e.g.,for flair_id in post_flair
).shortName
The short name of the widget.
styles
A
dict
with the keys"backgroundColor"
and"headerColor"
.subreddit
The
Subreddit
the button widget belongs to.templates
A
dict
that maps flair IDs to dictionaries that describe flairs.- mod() praw.models.WidgetModeration
Get an instance of
WidgetModeration
for this widget.Note
Using any of the methods of
WidgetModeration
will likely make the data in theSubredditWidgets
that this widget belongs to outdated. To remedy this, callrefresh()
.
RulesWidget
- class praw.models.RulesWidget(reddit: praw.Reddit, _data: Dict[str, Any])
Class to represent a rules widget.
widgets = reddit.subreddit("test").widgets rules_widget = None for widget in widgets.sidebar: if isinstance(widget, praw.models.RulesWidget): rules_widget = widget break from pprint import pprint pprint(rules_widget.data)
Update one:
new_styles = {"backgroundColor": "#FFFFFF", "headerColor": "#FF9900"} rules_widget.mod.update(display="compact", shortName="The LAWS", styles=new_styles)
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
data
A list of the subreddit rules. Can be iterated over by iterating over the
RulesWidget
(e.g.,for rule in rules_widget
).display
The display style of the widget, either
"full"
or"compact"
.id
The widget ID.
kind
The widget kind (always
"subreddit-rules"
).shortName
The short name of the widget.
styles
A
dict
with the keys"backgroundColor"
and"headerColor"
.subreddit
The
Subreddit
the button widget belongs to.- __init__(reddit: praw.Reddit, _data: Dict[str, Any])
Initialize a
RulesWidget
instance.
- mod() praw.models.WidgetModeration
Get an instance of
WidgetModeration
for this widget.Note
Using any of the methods of
WidgetModeration
will likely make the data in theSubredditWidgets
that this widget belongs to outdated. To remedy this, callrefresh()
.
Styles
- class praw.models.Styles(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Class to represent the style information of a widget.
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
backgroundColor
The background color of a widget, given as a hexadecimal (
0x######
).headerColor
The header color of a widget, given as a hexadecimal (
0x######
).
TextArea
- class praw.models.TextArea(reddit: praw.Reddit, _data: Dict[str, Any])
Class to represent a text area widget.
Find a text area in a subreddit:
widgets = reddit.subreddit("test").widgets text_area = None for widget in widgets.sidebar: if isinstance(widget, praw.models.TextArea): text_area = widget break print(text_area.text)
Create one:
widgets = reddit.subreddit("test").widgets styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} text_area = widgets.mod.add_text_area( short_name="My cool title", text="*Hello* **world**!", styles=styles )
For more information on creation, see
add_text_area()
.Update one:
new_styles = {"backgroundColor": "#FFFFFF", "headerColor": "#FF9900"} text_area = text_area.mod.update(shortName="My fav text", styles=new_styles)
Delete one:
text_area.mod.delete()
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
id
The widget ID.
kind
The widget kind (always
"textarea"
).shortName
The short name of the widget.
styles
A
dict
with the keys"backgroundColor"
and"headerColor"
.subreddit
The
Subreddit
the button widget belongs to.text
The widget’s text, as Markdown.
textHtml
The widget’s text, as HTML.
- mod() praw.models.WidgetModeration
Get an instance of
WidgetModeration
for this widget.Note
Using any of the methods of
WidgetModeration
will likely make the data in theSubredditWidgets
that this widget belongs to outdated. To remedy this, callrefresh()
.
Widget
- class praw.models.Widget(reddit: praw.Reddit, _data: Dict[str, Any])
Base class to represent a
Widget
.- mod() praw.models.WidgetModeration
Get an instance of
WidgetModeration
for this widget.Note
Using any of the methods of
WidgetModeration
will likely make the data in theSubredditWidgets
that this widget belongs to outdated. To remedy this, callrefresh()
.
Auth
- class praw.models.Auth(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Auth provides an interface to Reddit’s authorization.
- __init__(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Initialize a
PRAWBase
instance.- Parameters:
reddit – An instance of
Reddit
.
- authorize(code: str) str | None
Complete the web authorization flow and return the refresh token.
- Parameters:
code – The code obtained through the request to the redirect uri.
- Returns:
The obtained refresh token, if available, otherwise
None
.
The session’s active authorization will be updated upon success.
- implicit(*, access_token: str, expires_in: int, scope: str) None
Set the active authorization to be an implicit authorization.
- Parameters:
access_token – The access_token obtained from Reddit’s callback.
expires_in – The number of seconds the
access_token
is valid for. The origin of this value was returned from Reddit’s callback. You may need to subtract an offset before passing in this number to account for a delay between when Reddit prepared the response, and when you make this function call.scope – A space-delimited string of Reddit OAuth2 scope names as returned from Reddit’s callback.
- Raises:
InvalidImplicitAuth
ifReddit
was initialized for a non-installed application type.
- property limits: Dict[str, str | int | None]
Return a dictionary containing the rate limit info.
The keys are:
- Remaining:
The number of requests remaining to be made in the current rate limit window.
- Reset_timestamp:
A unix timestamp providing an upper bound on when the rate limit counters will reset.
- Used:
The number of requests made in the current rate limit window.
All values are initially
None
as these values are set in response to issued requests.The
reset_timestamp
value is an upper bound as the real timestamp is computed on Reddit’s end in preparation for sending the response. This value may change slightly within a given window due to slight changes in response times and rounding.
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit) Any
Return an instance of
cls
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.
- scopes() Set[str]
Return a set of scopes included in the current authorization.
For read-only authorizations this should return
{"*"}
.
- url(*, duration: str = 'permanent', implicit: bool = False, scopes: List[str], state: str) str
Return the URL used out-of-band to grant access to your application.
- Parameters:
duration – Either
"permanent"
or"temporary"
(default:"permanent"
)."temporary"
authorizations generate access tokens that last only 1 hour."permanent"
authorizations additionally generate a refresh token that expires 1 year after the last use and can be used indefinitely to generate new hour-long access tokens. This value is ignored whenimplicit=True
.implicit – For installed applications, this value can be set to use the implicit, rather than the code flow. When
True
, theduration
argument has no effect as only temporary tokens can be retrieved.scopes – A list of OAuth scopes to request authorization for.
state – A string that will be reflected in the callback to
redirect_uri
. This value should be temporarily unique to the client for whom the URL was generated for.
BaseList
CommentForest
- class praw.models.comment_forest.CommentForest(submission: praw.models.Submission, comments: List[praw.models.Comment] | None = None)
A forest of comments starts with multiple top-level comments.
Each of these comments can be a tree of replies.
- __getitem__(index: int)
Return the comment at position
index
in the list.This method is to be used like an array access, such as:
first_comment = submission.comments[0]
Alternatively, the presence of this method enables one to iterate over all top level comments, like so:
for comment in submission.comments: print(comment.body)
- __init__(submission: praw.models.Submission, comments: List[praw.models.Comment] | None = None)
Initialize a
CommentForest
instance.- Parameters:
submission – An instance of
Submission
that is the parent of the comments.comments – Initialize the forest with a list of comments (default:
None
).
- list() List[praw.models.Comment | praw.models.MoreComments]
Return a flattened list of all comments.
This list may contain
MoreComments
instances ifreplace_more()
was not called first.
- replace_more(*, limit: int | None = 32, threshold: int = 0) List[praw.models.MoreComments]
Update the comment forest by resolving instances of
MoreComments
.- Parameters:
limit – The maximum number of
MoreComments
instances to replace. Each replacement requires 1 API request. Set toNone
to have no limit, or to0
to remove allMoreComments
instances without additional requests (default:32
).threshold – The minimum number of children comments a
MoreComments
instance must have in order to be replaced.MoreComments
instances that represent “continue this thread” links unfortunately appear to have 0 children (default:0
).
- Returns:
A list of
MoreComments
instances that were not replaced.- Raises:
prawcore.TooManyRequests
when used concurrently.
For example, to replace up to 32
MoreComments
instances of a submission try:submission = reddit.submission("3hahrw") submission.comments.replace_more()
Alternatively, to replace
MoreComments
instances within the replies of a single comment try:comment = reddit.comment("d8r4im1") comment.refresh() comment.replies.replace_more()
Note
This method can take a long time as each replacement will discover at most 100 new
Comment
instances. As a result, consider looping and handling exceptions until the method returns successfully. For example:while True: try: submission.comments.replace_more() break except PossibleExceptions: print("Handling replace_more exception") sleep(1)
Warning
If this method is called, and the comments are refreshed, calling this method again will result in a
DuplicateReplaceException
.
CommentHelper
- class praw.models.listing.mixins.subreddit.CommentHelper(subreddit: praw.models.Subreddit)
Provide a set of functions to interact with a
Subreddit
’s comments.- __call__(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Comment]
Return a
ListingGenerator
for theSubreddit
’s comments.Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method should be used in a way similar to the example below:
for comment in reddit.subreddit("test").comments(limit=25): print(comment.author)
- __init__(subreddit: praw.models.Subreddit)
Initialize a
CommentHelper
instance.
Config
- class praw.config.Config(site_name: str, config_interpolation: str | None = None, **settings: str)
A class containing the configuration for a Reddit site.
- __init__(site_name: str, config_interpolation: str | None = None, **settings: str)
Initialize a
Config
instance.
- property short_url: str
Return the short url.
- Raises:
ClientException
if it is not set.
DomainListing
- class praw.models.DomainListing(reddit: praw.Reddit, domain: str)
Provide a set of functions to interact with domain listings.
- __init__(reddit: praw.Reddit, domain: str)
Initialize a
DomainListing
instance.- Parameters:
reddit – An instance of
Reddit
.domain – The domain for which to obtain listings.
- controversial(*, time_filter: str = 'all', **generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for controversial items.- Parameters:
time_filter – Can be one of:
"all"
,"day"
,"hour"
,"month"
,"week"
, or"year"
(default:"all"
).- Raises:
ValueError
iftime_filter
is invalid.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").controversial(time_filter="week") reddit.multireddit(redditor="samuraisam", name="programming").controversial( time_filter="day" ) reddit.redditor("spez").controversial(time_filter="month") reddit.redditor("spez").comments.controversial(time_filter="year") reddit.redditor("spez").submissions.controversial(time_filter="all") reddit.subreddit("all").controversial(time_filter="hour")
- hot(**generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for hot items.Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").hot() reddit.multireddit(redditor="samuraisam", name="programming").hot() reddit.redditor("spez").hot() reddit.redditor("spez").comments.hot() reddit.redditor("spez").submissions.hot() reddit.subreddit("all").hot()
- new(**generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for new items.Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").new() reddit.multireddit(redditor="samuraisam", name="programming").new() reddit.redditor("spez").new() reddit.redditor("spez").comments.new() reddit.redditor("spez").submissions.new() reddit.subreddit("all").new()
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit) Any
Return an instance of
cls
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.
- random_rising(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Submission]
Return a
ListingGenerator
for random rising submissions.Additional keyword arguments are passed in the initialization of
ListingGenerator
.For example, to get random rising submissions for r/test:
for submission in reddit.subreddit("test").random_rising(): print(submission.title)
- rising(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Submission]
Return a
ListingGenerator
for rising submissions.Additional keyword arguments are passed in the initialization of
ListingGenerator
.For example, to get rising submissions for r/test:
for submission in reddit.subreddit("test").rising(): print(submission.title)
- top(*, time_filter: str = 'all', **generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for top items.- Parameters:
time_filter – Can be one of:
"all"
,"day"
,"hour"
,"month"
,"week"
, or"year"
(default:"all"
).- Raises:
ValueError
iftime_filter
is invalid.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").top(time_filter="week") reddit.multireddit(redditor="samuraisam", name="programming").top(time_filter="day") reddit.redditor("spez").top(time_filter="month") reddit.redditor("spez").comments.top(time_filter="year") reddit.redditor("spez").submissions.top(time_filter="all") reddit.subreddit("all").top(time_filter="hour")
DraftList
Emoji
- class praw.models.reddit.emoji.Emoji(reddit: praw.Reddit, subreddit: praw.models.Subreddit, name: str, _data: Dict[str, Any] | None = None)
An individual
Emoji
object.Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
mod_flair_only
Whether the emoji is restricted for mod use only.
name
The name of the emoji.
post_flair_allowed
Whether the emoji may appear in post flair.
url
The URL of the emoji image.
user_flair_allowed
Whether the emoji may appear in user flair.
- __init__(reddit: praw.Reddit, subreddit: praw.models.Subreddit, name: str, _data: Dict[str, Any] | None = None)
Initialize an
Emoji
instance.
- delete()
Delete an emoji from this subreddit by
Emoji
.To delete
"emoji"
as an emoji on r/test try:reddit.subreddit("test").emoji["emoji"].delete()
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit) Any
Return an instance of
cls
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.
- update(*, mod_flair_only: bool | None = None, post_flair_allowed: bool | None = None, user_flair_allowed: bool | None = None)
Update the permissions of an emoji in this subreddit.
- Parameters:
mod_flair_only – Indicate whether the emoji is restricted to mod use only. Respects pre-existing settings if not provided.
post_flair_allowed – Indicate whether the emoji may appear in post flair. Respects pre-existing settings if not provided.
user_flair_allowed – Indicate whether the emoji may appear in user flair. Respects pre-existing settings if not provided.
Note
In order to retain pre-existing values for those that are not explicitly passed, a network request is issued. To avoid that network request, explicitly provide all values.
To restrict the emoji
"emoji"
in r/test to mod use only, try:reddit.subreddit("test").emoji["emoji"].update(mod_flair_only=True)
FullnameMixin
InboxableMixin
- class praw.models.reddit.mixins.InboxableMixin
Interface for
RedditBase
subclasses that originate from the inbox.- __init__()
- block()
Block the user who sent the item.
Note
This method pertains only to objects which were retrieved via the inbox.
Example usage:
comment = reddit.comment("dkk4qjd") comment.block() # or, identically: comment.author.block()
- collapse()
Mark the item as collapsed.
Note
This method pertains only to objects which were retrieved via the inbox.
Example usage:
inbox = reddit.inbox() # select first inbox item and collapse it message = next(inbox) message.collapse()
See also
- mark_read()
Mark a single inbox item as read.
Note
This method pertains only to objects which were retrieved via the inbox.
Example usage:
inbox = reddit.inbox.unread() for message in inbox: # process unread messages ...
See also
To mark the whole inbox as read with a single network request, use
Inbox.mark_all_read()
- mark_unread()
Mark the item as unread.
Note
This method pertains only to objects which were retrieved via the inbox.
Example usage:
inbox = reddit.inbox(limit=10) for message in inbox: # process messages ...
See also
- unblock_subreddit()
Unblock a subreddit.
Note
This method pertains only to objects which were retrieved via the inbox.
For example, to unblock all blocked subreddits that you can find by going through your inbox:
from praw.models import SubredditMessage subs = set() for item in reddit.inbox.messages(limit=None): if isinstance(item, SubredditMessage): if ( item.subject == "[message from blocked subreddit]" and str(item.subreddit) not in subs ): item.unblock_subreddit() subs.add(str(item.subreddit))
- uncollapse()
Mark the item as uncollapsed.
Note
This method pertains only to objects which were retrieved via the inbox.
Example usage:
inbox = reddit.inbox() # select first inbox item and uncollapse it message = next(inbox) message.uncollapse()
See also
ListingGenerator
- class praw.models.ListingGenerator(reddit: praw.Reddit, url: str, limit: int = 100, params: Dict[str, str | int] | None = None)
Instances of this class generate
RedditBase
instances.Warning
This class should not be directly utilized. Instead, you will find a number of methods that return instances of the class here.
- __init__(reddit: praw.Reddit, url: str, limit: int = 100, params: Dict[str, str | int] | None = None)
Initialize a
ListingGenerator
instance.- Parameters:
reddit – An instance of
Reddit
.url – A URL returning a Reddit listing.
limit – The number of content entries to fetch. If
limit
isNone
, then fetch as many entries as possible. Most of Reddit’s listings contain a maximum of 1000 items, and are returned 100 at a time. This class will automatically issue all necessary requests (default:100
).params – A dictionary containing additional query string parameters to send with the request.
- __iter__() Iterator[Any]
Permit
ListingGenerator
to operate as an iterator.
ModAction
- class praw.models.ModAction(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Represent a moderator action.
- __init__(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Initialize a
PRAWBase
instance.- Parameters:
reddit – An instance of
Reddit
.
- property mod: praw.models.Redditor
Return the
Redditor
who the action was issued by.
ModeratedList
Modmail
- class praw.models.reddit.subreddit.Modmail(subreddit: praw.models.Subreddit)
Provides modmail functions for a
Subreddit
.For example, to send a new modmail from r/test to u/spez with the subject
"test"
along with a message body of"hello"
:reddit.subreddit("test").modmail.create(subject="test", body="hello", recipient="spez")
- __call__(id: str | None = None, mark_read: bool = False)
Return an individual conversation.
- Parameters:
id – A reddit base36 conversation ID, e.g.,
"2gmz"
.mark_read – If
True
, conversation is marked as read (default:False
).
For example:
reddit.subreddit("test").modmail("2gmz", mark_read=True)
To print all messages from a conversation as Markdown source:
conversation = reddit.subreddit("test").modmail("2gmz", mark_read=True) for message in conversation.messages: print(message.body_markdown)
ModmailConversation.user
is a special instance ofRedditor
with extra attributes describing the non-moderator user’s recent posts, comments, and modmail messages within the subreddit, as well as information on active bans and mutes. This attribute does not exist on internal moderator discussions.For example, to print the user’s ban status:
conversation = reddit.subreddit("test").modmail("2gmz", mark_read=True) print(conversation.user.ban_status)
To print a list of recent submissions by the user:
conversation = reddit.subreddit("test").modmail("2gmz", mark_read=True) print(conversation.user.recent_posts)
- __init__(subreddit: praw.models.Subreddit)
Initialize a
Modmail
instance.
- bulk_read(*, other_subreddits: List[str | praw.models.Subreddit] | None = None, state: str | None = None) List[ModmailConversation]
Mark conversations for subreddit(s) as read.
Note
Due to server-side restrictions, r/all is not a valid subreddit for this method. Instead, use
subreddits()
to get a list of subreddits using the new modmail.- Parameters:
other_subreddits – A list of
Subreddit
instances for which to mark conversations (default:None
).state – Can be one of:
"all"
,"archived"
, or"highlighted"
,"inprogress"
,"join_requests"
,"mod"
,"new"
,"notifications"
, or"appeals"
(default:"all"
)."all"
does not include internal, archived, or appeals conversations.
- Returns:
A list of
ModmailConversation
instances that were marked read.
For example, to mark all notifications for a subreddit as read:
subreddit = reddit.subreddit("test") subreddit.modmail.bulk_read(state="notifications")
- conversations(*, after: str | None = None, other_subreddits: List[praw.models.Subreddit] | None = None, sort: str | None = None, state: str | None = None, **generator_kwargs) Iterator[ModmailConversation]
Generate
ModmailConversation
objects for subreddit(s).- Parameters:
after –
A base36 modmail conversation id. When provided, the listing begins after this conversation (default:
None
).Deprecated since version 7.4.0: This parameter is deprecated and will be removed in PRAW 8.0. This method will automatically fetch the next batch. Please pass it in the
params
argument like so:for convo in subreddit.modmail.conversations(params={"after": "qovbn"}): # process conversation ...
other_subreddits – A list of
Subreddit
instances for which to fetch conversations (default:None
).sort – Can be one of:
"mod"
,"recent"
,"unread"
, or"user"
(default:"recent"
).state – Can be one of:
"all"
,"archived"
,"highlighted"
,"inprogress"
,"join_requests"
,"mod"
,"new"
,"notifications"
, or"appeals"
(default:"all"
)."all"
does not include internal, archived, or appeals conversations.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.For example:
conversations = reddit.subreddit("all").modmail.conversations(state="mod")
- create(*, author_hidden: bool = False, body: str, recipient: str | praw.models.Redditor, subject: str) ModmailConversation
Create a new
ModmailConversation
.- Parameters:
author_hidden – When
True
, author is hidden from non-moderators (default:False
).body – The message body. Cannot be empty.
recipient – The recipient; a username or an instance of
Redditor
.subject – The message subject. Cannot be empty.
- Returns:
A
ModmailConversation
object for the newly created conversation.
subreddit = reddit.subreddit("test") redditor = reddit.redditor("bboe") subreddit.modmail.create(subject="Subject", body="Body", recipient=redditor)
- subreddits() Generator[praw.models.Subreddit, None, None]
Yield subreddits using the new modmail that the user moderates.
For example:
subreddits = reddit.subreddit("all").modmail.subreddits()
- unread_count() Dict[str, int]
Return unread conversation count by conversation state.
At time of writing, possible states are:
"archived"
,"highlighted"
,"inprogress"
,"join_requests"
,"mod"
,"new"
,"notifications"
, or"appeals"
.- Returns:
A dict mapping conversation states to unread counts.
For example, to print the count of unread moderator discussions:
subreddit = reddit.subreddit("test") unread_counts = subreddit.modmail.unread_count() print(unread_counts["mod"])
ModmailMessage
- class praw.models.ModmailMessage(reddit: praw.Reddit, _data: Dict[str, Any] | None, _extra_attribute_to_check: str | None = None, _fetched: bool = False, _str_field: bool = True)
A class for modmail messages.
PollData
- class praw.models.reddit.poll.PollData(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Class to represent poll data on a poll submission.
If
submission
is a pollSubmission
, access the poll data like so:poll_data = submission.poll_data print(f"There are {poll_data.total_vote_count} votes total.") print("The options are:") for option in poll_data.options: print(f"{option} ({option.vote_count} votes)") print(f"I voted for {poll_data.user_selection}.")
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
options
A list of
PollOption
of the poll.total_vote_count
The total number of votes cast in the poll.
user_selection
The poll option selected by the authenticated user (possibly
None
).voting_end_timestamp
Time the poll voting closes, represented in Unix Time.
- __init__(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Initialize a
PRAWBase
instance.- Parameters:
reddit – An instance of
Reddit
.
- option(option_id: str) PollOption
Get the option with the specified ID.
- Parameters:
option_id – The ID of a poll option, as a
str
.- Returns:
The specified
PollOption
.- Raises:
KeyError
if no option exists with the specified ID.
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit) Any
Return an instance of
cls
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.
- user_selection() PollOption | None
Get the user’s selection in this poll, if any.
- Returns:
The user’s selection as a
PollOption
, orNone
if there is no choice.
PollOption
- class praw.models.reddit.poll.PollOption(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Class to represent one option of a poll.
If
submission
is a pollSubmission
, access the poll’s options like so:poll_data = submission.poll_data # By index -- print the first option print(poll_data.options[0]) # By ID -- print the option with ID "576797" print(poll_data.option("576797"))
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
id
ID of the poll option.
text
The text of the poll option.
vote_count
The number of votes the poll option has received.
PartialRedditor
PRAWBase
Preferences
- class praw.models.Preferences(reddit: praw.Reddit)
A class for Reddit preferences.
The
Preferences
class provides access to the Reddit preferences of the currently authenticated user.- __call__() Dict[str, str | int | bool]
Return the preference settings of the authenticated user as a dict.
This method is intended to be accessed as
reddit.user.preferences()
like so:preferences = reddit.user.preferences() print(preferences["show_link_flair"])
See https://www.reddit.com/dev/api#GET_api_v1_me_prefs for the list of possible values.
- __init__(reddit: praw.Reddit)
Initialize a
Preferences
instance.- Parameters:
reddit – The
Reddit
instance.
- update(**preferences: bool | int | str)
Modify the specified settings.
- Parameters:
accept_pms – Who can send you personal messages (one of
"everyone"
or"whitelisted"
).activity_relevant_ads – Allow Reddit to use your activity on Reddit to show you more relevant advertisements.
allow_clicktracking – Allow Reddit to log my outbound clicks for personalization.
beta – I would like to beta test features for Reddit.
clickgadget – Show me links I’ve recently viewed.
collapse_read_messages – Collapse messages after I’ve read them.
compress – Compress the link display.
creddit_autorenew – Use a creddit to automatically renew my gold if it expires.
default_comment_sort – Default comment sort (one of
"confidence"
,"top"
,"new"
,"controversial"
,"old"
,"random"
,"qa"
, or"live"
).domain_details (bool) – Show additional details in the domain text when available, such as the source subreddit or the content author’s url/name.
email_chat_request (bool) – Send chat requests as emails.
email_comment_reply (bool) – Send comment replies as emails.
email_digests (bool) – Send email digests.
email_messages (bool) – Send messages as emails.
email_post_reply (bool) – Send post replies as emails.
email_private_message (bool) – Send private messages as emails.
email_unsubscribe_all (bool) – Unsubscribe from all emails.
email_upvote_comment (bool) – Send comment upvote updates as emails.
email_upvote_post (bool) – Send post upvote updates as emails.
email_user_new_follower (bool) – Send new follower alerts as emails.
email_username_mention (bool) – Send username mentions as emails.
enable_default_themes (bool) – Use Reddit theme.
feed_recommendations_enabled (bool) – Enable feed recommendations.
geopopular (str) – Location (one of
"GLOBAL"
,"AR"
,"AU"
,"BG"
,"CA"
,"CL"
,"CO"
,"CZ"
,"FI"
,"GB"
,"GR"
,"HR"
,"HU"
,"IE"
,"IN"
,"IS"
,"JP"
,"MX"
,"MY"
,"NZ"
,"PH"
,"PL"
,"PR"
,"PT"
,"RO"
,"RS"
,"SE"
,"SG"
,"TH"
,"TR"
,"TW"
,"US"
,"US_AK"
,"US_AL"
,"US_AR"
,"US_AZ"
,"US_CA"
,"US_CO"
,"US_CT"
,"US_DC"
,"US_DE"
,"US_FL"
,"US_GA"
,"US_HI"
,"US_IA"
,"US_ID"
,"US_IL"
,"US_IN"
,"US_KS"
,"US_KY"
,"US_LA"
,"US_MA"
,"US_MD"
,"US_ME"
,"US_MI"
,"US_MN"
,"US_MO"
,"US_MS"
,"US_MT"
,"US_NC"
,"US_ND"
,"US_NE"
,"US_NH"
,"US_NJ"
,"US_NM"
,"US_NV"
,"US_NY"
,"US_OH"
,"US_OK"
,"US_OR"
,"US_PA"
,"US_RI"
,"US_SC"
,"US_SD"
,"US_TN"
,"US_TX"
,"US_UT"
,"US_VA"
,"US_VT"
,"US_WA"
,"US_WI"
,"US_WV"
, or"US_WY"
).hide_ads (bool) – Hide ads.
hide_downs (bool) – Don’t show me submissions after I’ve downvoted them, except my own.
hide_from_robots (bool) – Don’t allow search engines to index my user profile.
hide_ups (bool) – Don’t show me submissions after I’ve upvoted them, except my own.
highlight_controversial (bool) – Show a dagger on comments voted controversial.
highlight_new_comments (bool) – Highlight new comments.
ignore_suggested_sort (bool) – Ignore suggested sorts.
in_redesign_beta (bool) – In redesign beta.
label_nsfw (bool) – Label posts that are not safe for work.
lang (str) – Interface language (IETF language tag, underscore separated).
legacy_search (bool) – Show legacy search page.
live_orangereds (bool) – Send message notifications in my browser.
mark_messages_read (bool) – Mark messages as read when I open my inbox.
media (str) – Thumbnail preference (one of
"on"
,"off"
, or"subreddit"
).media_preview (str) – Media preview preference (one of
"on"
,"off"
, or"subreddit"
).min_comment_score (int) – Don’t show me comments with a score less than this number (between
-100
and100
).min_link_score (int) – Don’t show me submissions with a score less than this number (between
-100
and100
).monitor_mentions (bool) – Notify me when people say my username.
newwindow (bool) – Open links in a new window.
nightmode (bool) – Enable night mode.
no_profanity (bool) – Don’t show thumbnails or media previews for anything labeled NSFW.
num_comments (int) – Display this many comments by default (between
1
and500
).numsites (int) – Number of links to display at once (between
1
and100
).organic (bool) – Show the spotlight box on the home feed.
other_theme (str) – Subreddit theme to use (subreddit name).
over_18 (bool) – I am over eighteen years old and willing to view adult content.
private_feeds (bool) – Enable private RSS feeds.
profile_opt_out (bool) – View user profiles on desktop using legacy mode.
public_votes (bool) – Make my votes public.
research (bool) – Allow my data to be used for research purposes.
search_include_over_18 (bool) – Include not safe for work (NSFW) search results in searches.
send_crosspost_messages (bool) – Send crosspost messages.
send_welcome_messages (bool) – Send welcome messages.
show_flair (bool) – Show user flair.
show_gold_expiration (bool) – Show how much gold you have remaining on your userpage.
show_link_flair (bool) – Show link flair.
show_location_based_recommendations (bool) – Show location based recommendations.
show_presence (bool) – Show presence.
show_promote (bool) – Show promote.
show_stylesheets (bool) – Allow subreddits to show me custom themes.
show_trending (bool) – Show trending subreddits on the home feed.
show_twitter (bool) – Show a link to your Twitter account on your profile.
store_visits (bool) – Store visits.
theme_selector (bool) – Theme selector (subreddit name).
third_party_data_personalized_ads (bool) – Allow Reddit to use data provided by third-parties to show you more relevant advertisements on Reddit.
third_party_personalized_ads (bool) – Allow personalization of advertisements.
third_party_site_data_personalized_ads (bool) – Allow personalization of advertisements using third-party website data.
third_party_site_data_personalized_content (bool) – Allow personalization of content using third-party website data.
threaded_messages (bool) – Show message conversations in the inbox.
threaded_modmail (bool) – Enable threaded modmail display.
top_karma_subreddits (bool) – Top karma subreddits.
use_global_defaults (bool) – Use global defaults.
video_autoplay (bool) – Autoplay Reddit videos on the desktop comments page.
Additional keyword arguments can be provided to handle new settings as Reddit introduces them.
See https://www.reddit.com/dev/api#PATCH_api_v1_me_prefs for the most up-to-date list of possible parameters.
This is intended to be used like so:
reddit.user.preferences.update(show_link_flair=True)
This method returns the new state of the preferences as a
dict
, which can be used to check whether a change went through.original_preferences = reddit.user.preferences() new_preferences = reddit.user.preferences.update(invalid_param=123) print(original_preferences == new_preferences) # True, no change
Warning
Passing an unknown parameter name or an illegal value (such as an int when a boolean is expected) does not result in an error from the Reddit API. As a consequence, any invalid input will fail silently. To verify that changes have been made, use the return value of this method, which is a dict of the preferences after the update action has been performed.
Some preferences have names that are not valid keyword arguments in Python. To update these, construct a
dict
and use**
to unpack it as keyword arguments:reddit.user.preferences.update(**{"third_party_data_personalized_ads": False})
RedditBase
- class praw.models.reddit.base.RedditBase(reddit: praw.Reddit, _data: Dict[str, Any] | None, _extra_attribute_to_check: str | None = None, _fetched: bool = False, _str_field: bool = True)
Base class that represents actual Reddit objects.
RedditorList
RedditorStream
- class praw.models.reddit.redditor.RedditorStream(redditor: praw.models.Redditor)
Provides submission and comment streams.
- __init__(redditor: praw.models.Redditor)
Initialize a
RedditorStream
instance.- Parameters:
redditor – The redditor associated with the streams.
- comments(**stream_options: str | int | Dict[str, str]) Generator[praw.models.Comment, None, None]
Yield new comments as they become available.
Comments are yielded oldest first. Up to 100 historical comments will initially be returned.
Keyword arguments are passed to
stream_generator()
.For example, to retrieve all new comments made by redditor u/spez, try:
for comment in reddit.redditor("spez").stream.comments(): print(comment)
- submissions(**stream_options: str | int | Dict[str, str]) Generator[praw.models.Submission, None, None]
Yield new submissions as they become available.
Submissions are yielded oldest first. Up to 100 historical submissions will initially be returned.
Keyword arguments are passed to
stream_generator()
.For example, to retrieve all new submissions made by redditor u/spez, try:
for submission in reddit.redditor("spez").stream.submissions(): print(submission)
RemovalReason
- class praw.models.reddit.removal_reasons.RemovalReason(reddit: praw.Reddit, subreddit: praw.models.Subreddit, id: str | None = None, reason_id: str | None = None, _data: Dict[str, Any] | None = None)
An individual Removal Reason object.
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
id
The ID of the removal reason.
message
The message of the removal reason.
title
The title of the removal reason.
- __init__(reddit: praw.Reddit, subreddit: praw.models.Subreddit, id: str | None = None, reason_id: str | None = None, _data: Dict[str, Any] | None = None)
Initialize a
RemovalReason
instance.
- delete()
Delete a removal reason from this subreddit.
To delete
"141vv5c16py7d"
from r/test try:reddit.subreddit("test").mod.removal_reasons["141vv5c16py7d"].delete()
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit) Any
Return an instance of
cls
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.
- update(*, message: str | None = None, title: str | None = None)
Update the removal reason from this subreddit.
Note
Existing values will be used for any unspecified arguments.
- Parameters:
message – The removal reason’s new message.
title – The removal reason’s new title.
To update
"141vv5c16py7d"
from r/test try:reddit.subreddit("test").mod.removal_reasons["141vv5c16py7d"].update( title="New title", message="New message" )
Rule
- class praw.models.Rule(reddit: praw.Reddit, subreddit: praw.models.Subreddit | None = None, short_name: str | None = None, _data: Dict[str, str] | None = None)
An individual
Rule
object.Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
created_utc
Time the rule was created, represented in Unix Time.
description
The description of the rule, if provided, otherwise a blank string.
kind
The kind of rule. Can be
"link"
,comment"
, or"all"
.priority
Represents where the rule is ranked. For example, the first rule is at priority
0
. Serves as an index number on the list of rules.short_name
The name of the rule.
violation_reason
The reason that is displayed on the report menu for the rule.
- __init__(reddit: praw.Reddit, subreddit: praw.models.Subreddit | None = None, short_name: str | None = None, _data: Dict[str, str] | None = None)
Initialize a
Rule
instance.
- mod() praw.models.reddit.rules.RuleModeration
Contain methods used to moderate rules.
To delete
"No spam"
from r/test try:reddit.subreddit("test").rules["No spam"].mod.delete()
To update
"No spam"
from r/test try:reddit.subreddit("test").removal_reasons["No spam"].mod.update( description="Don't do this!", violation_reason="Spam post" )
Stylesheet
- class praw.models.Stylesheet(reddit: praw.Reddit, _data: Dict[str, Any] | None)
Represent a stylesheet.
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
images
A list of images used by the stylesheet.
stylesheet
The contents of the stylesheet, as CSS.
SubListing
- class praw.models.listing.mixins.redditor.SubListing(reddit: praw.Reddit, base_path: str, subpath: str)
Helper class for generating
ListingGenerator
objects.- __init__(reddit: praw.Reddit, base_path: str, subpath: str)
Initialize a
SubListing
instance.- Parameters:
reddit – An instance of
Reddit
.base_path – The path to the object up to this point.
subpath – The additional path to this sublisting.
- controversial(*, time_filter: str = 'all', **generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for controversial items.- Parameters:
time_filter – Can be one of:
"all"
,"day"
,"hour"
,"month"
,"week"
, or"year"
(default:"all"
).- Raises:
ValueError
iftime_filter
is invalid.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").controversial(time_filter="week") reddit.multireddit(redditor="samuraisam", name="programming").controversial( time_filter="day" ) reddit.redditor("spez").controversial(time_filter="month") reddit.redditor("spez").comments.controversial(time_filter="year") reddit.redditor("spez").submissions.controversial(time_filter="all") reddit.subreddit("all").controversial(time_filter="hour")
- hot(**generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for hot items.Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").hot() reddit.multireddit(redditor="samuraisam", name="programming").hot() reddit.redditor("spez").hot() reddit.redditor("spez").comments.hot() reddit.redditor("spez").submissions.hot() reddit.subreddit("all").hot()
- new(**generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for new items.Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").new() reddit.multireddit(redditor="samuraisam", name="programming").new() reddit.redditor("spez").new() reddit.redditor("spez").comments.new() reddit.redditor("spez").submissions.new() reddit.subreddit("all").new()
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit) Any
Return an instance of
cls
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.
- top(*, time_filter: str = 'all', **generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for top items.- Parameters:
time_filter – Can be one of:
"all"
,"day"
,"hour"
,"month"
,"week"
, or"year"
(default:"all"
).- Raises:
ValueError
iftime_filter
is invalid.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").top(time_filter="week") reddit.multireddit(redditor="samuraisam", name="programming").top(time_filter="day") reddit.redditor("spez").top(time_filter="month") reddit.redditor("spez").comments.top(time_filter="year") reddit.redditor("spez").submissions.top(time_filter="all") reddit.subreddit("all").top(time_filter="hour")
SubredditMessage
- class praw.models.SubredditMessage(reddit: praw.Reddit, _data: Dict[str, Any])
A class for messages to a subreddit.
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
author
Provides an instance of
Redditor
.body
The body of the message, as Markdown.
body_html
The body of the message, as HTML.
created_utc
Time the message was created, represented in Unix Time.
dest
Provides an instance of
Redditor
. The recipient of the message.id
The ID of the message.
name
The full ID of the message, prefixed with
t4_
.subject
The subject of the message.
subreddit
If the message was sent from a subreddit, provides an instance of
Subreddit
.was_comment
Whether or not the message was a comment reply.
- block()
Block the user who sent the item.
Note
This method pertains only to objects which were retrieved via the inbox.
Example usage:
comment = reddit.comment("dkk4qjd") comment.block() # or, identically: comment.author.block()
- collapse()
Mark the item as collapsed.
Note
This method pertains only to objects which were retrieved via the inbox.
Example usage:
inbox = reddit.inbox() # select first inbox item and collapse it message = next(inbox) message.collapse()
See also
- delete()
Delete the message.
Note
Reddit does not return an indication of whether or not the message was successfully deleted.
For example, to delete the most recent message in your inbox:
next(reddit.inbox.all()).delete()
- property fullname: str
Return the object’s fullname.
A fullname is an object’s kind mapping like
t3
followed by an underscore and the object’s base36 ID, e.g.,t1_c5s96e0
.
- mark_read()
Mark a single inbox item as read.
Note
This method pertains only to objects which were retrieved via the inbox.
Example usage:
inbox = reddit.inbox.unread() for message in inbox: # process unread messages ...
See also
To mark the whole inbox as read with a single network request, use
Inbox.mark_all_read()
- mark_unread()
Mark the item as unread.
Note
This method pertains only to objects which were retrieved via the inbox.
Example usage:
inbox = reddit.inbox(limit=10) for message in inbox: # process messages ...
See also
- mute()
Mute the sender of this
SubredditMessage
.For example, to mute the sender of the first
SubredditMessage
in the authenticated users’ inbox:from praw.models import SubredditMessage msg = next( message for message in reddit.inbox.all() if isinstance(message, SubredditMessage) ) msg.mute()
- property parent: praw.models.Message | None
Return the parent of the message if it exists.
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit)
Return an instance of
Message
orSubredditMessage
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.
- reply(body: str) praw.models.Comment | praw.models.Message | None
Reply to the object.
- Parameters:
body – The Markdown formatted content for a comment.
- Returns:
A
Comment
orMessage
object for the newly created comment or message orNone
if Reddit doesn’t provide one.- Raises:
prawcore.exceptions.Forbidden
when attempting to reply to some items, such as locked submissions/comments or non-replyable messages.
A
None
value can be returned if the target is a comment or submission in a quarantined subreddit and the authenticated user has not opt-ed into viewing the content. When this happens the comment will be successfully created on Reddit and can be retried by drawing the comment from the user’s comment history.Example usage:
submission = reddit.submission("5or86n") submission.reply("reply") comment = reddit.comment("dxolpyc") comment.reply("reply")
- unblock_subreddit()
Unblock a subreddit.
Note
This method pertains only to objects which were retrieved via the inbox.
For example, to unblock all blocked subreddits that you can find by going through your inbox:
from praw.models import SubredditMessage subs = set() for item in reddit.inbox.messages(limit=None): if isinstance(item, SubredditMessage): if ( item.subject == "[message from blocked subreddit]" and str(item.subreddit) not in subs ): item.unblock_subreddit() subs.add(str(item.subreddit))
- uncollapse()
Mark the item as uncollapsed.
Note
This method pertains only to objects which were retrieved via the inbox.
Example usage:
inbox = reddit.inbox() # select first inbox item and uncollapse it message = next(inbox) message.uncollapse()
See also
- unmute()
Unmute the sender of this
SubredditMessage
.For example, to unmute the sender of the first
SubredditMessage
in the authenticated users’ inbox:from praw.models import SubredditMessage msg = next( message for message in reddit.inbox.all() if isinstance(message, SubredditMessage) ) msg.unmute()
Token Manager
Token Manager classes.
There should be a 1-to-1 mapping between an instance of a subclass of
BaseTokenManager
and a Reddit
instance.
A few proof of concept token manager classes are provided here, but it is expected that PRAW users will create their own token manager classes suitable for their needs.
Deprecated since version 7.4.0: Tokens managers have been deprecated and will be removed in the near future.
- class praw.util.token_manager.BaseTokenManager
An abstract class for all token managers.
- __init__()
Initialize a
BaseTokenManager
instance.
- abstract post_refresh_callback(authorizer)
Handle callback that is invoked after a refresh token is used.
- Parameters:
authorizer – The
prawcore.Authorizer
instance used containingaccess_token
andrefresh_token
attributes.
This function will be called after refreshing the access and refresh tokens. This callback can be used for saving the updated
refresh_token
.
- abstract pre_refresh_callback(authorizer)
Handle callback that is invoked before refreshing PRAW’s authorization.
- Parameters:
authorizer – The
prawcore.Authorizer
instance used containingaccess_token
andrefresh_token
attributes.
This callback can be used to inspect and modify the attributes of the
prawcore.Authorizer
instance, such as setting therefresh_token
.
- class praw.util.token_manager.FileTokenManager(filename)
Provides a single-file based token manager.
It is expected that the file with the initial
refresh_token
is created prior to use.Warning
The same
file
should not be used by more than one instance of this class concurrently. Doing so may result in data corruption. Consider usingSQLiteTokenManager
if you want more than one instance of PRAW to concurrently manage a specificrefresh_token
chain.- __init__(filename)
Initialize a
FileTokenManager
instance.- Parameters:
filename – The file the contains the refresh token.
- post_refresh_callback(authorizer)
Update the saved copy of the refresh token.
- pre_refresh_callback(authorizer)
Load the refresh token from the file.
- class praw.util.token_manager.SQLiteTokenManager(*, database, key)
Provides a SQLite3 based token manager.
Unlike,
FileTokenManager
, the initial database need not be created ahead of time, as it’ll automatically be created on first use. However, initial refresh tokens will need to be registered viaregister()
prior to use.Warning
This class is untested on Windows because we encountered file locking issues in the test environment.
- __init__(*, database, key)
Initialize a
SQLiteTokenManager
instance.- Parameters:
database – The path to the SQLite database.
key – The key used to locate the refresh token. This
key
can be anything. You might use theclient_id
if you expect to have unique a refresh token for eachclient_id
, or you might use a redditor’susername
if you’re managing multiple users’ authentications.
- is_registered()
Return whether or not
key
already has arefresh_token
.
- post_refresh_callback(authorizer)
Update the refresh token in the database.
- pre_refresh_callback(authorizer)
Load the refresh token from the database.
- register(refresh_token)
Register the initial refresh token in the database.
- Returns:
True
ifrefresh_token
is saved to the database, otherwise,False
if there is already arefresh_token
for the associatedkey
.
Trophy
- class praw.models.Trophy(reddit: praw.Reddit, _data: Dict[str, Any])
Represent a trophy.
End users should not instantiate this class directly.
Redditor.trophies()
can be used to get a list of the redditor’s trophies.Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
award_id
The ID of the trophy (sometimes
None
).description
The description of the trophy (sometimes
None
).icon_40
The URL of a 41x41 px icon for the trophy.
icon_70
The URL of a 71x71 px icon for the trophy.
name
The name of the trophy.
url
A relevant URL (sometimes
None
).
UserSubreddit
- class praw.models.UserSubreddit(reddit: praw.Reddit, *args, **kwargs)
A class for
User
Subreddits.To obtain an instance of this class execute:
subreddit = reddit.user.me().subreddit
Typical Attributes
Note
This table describes attributes that typically belong to objects of this class. PRAW dynamically provides the attributes that Reddit returns via the API. Since those attributes are subject to change on Reddit’s end, PRAW makes no effort to document any new/removed/changed attributes, other than to instruct you on how to discover what is available. As a result, this table of attributes may not be complete. See Determine Available Attributes of an Object for detailed information.
If you would like to add an attribute to this table, feel free to open a pull request.
Attribute
Description
can_assign_link_flair
Whether users can assign their own link flair.
can_assign_user_flair
Whether users can assign their own user flair.
created_utc
Time the subreddit was created, represented in Unix Time.
description
Subreddit description, in Markdown.
description_html
Subreddit description, in HTML.
display_name
Name of the subreddit.
id
ID of the subreddit.
name
Fullname of the subreddit.
over18
Whether the subreddit is NSFW.
public_description
Description of the subreddit, shown in searches and on the “You must be invited to visit this community” page (if applicable).
spoilers_enabled
Whether the spoiler tag feature is enabled.
subscribers
Count of subscribers. This will be
0
unless unless the authenticated user is a moderator.user_is_banned
Whether the authenticated user is banned.
user_is_moderator
Whether the authenticated user is a moderator.
user_is_subscriber
Whether the authenticated user is subscribed.
- __getitem__(item)
Show deprecation notice for dict method
__getitem__
.
- __init__(reddit: praw.Reddit, *args, **kwargs)
Initialize an
UserSubreddit
instance.- Parameters:
reddit – An instance of
Reddit
.
Note
This class should not be initialized directly. Instead, obtain an instance via:
reddit.user.me().subreddit
orreddit.redditor("redditor_name").subreddit
.
- banned() praw.models.reddit.subreddit.SubredditRelationship
Provide an instance of
SubredditRelationship
.For example, to ban a user try:
reddit.subreddit("test").banned.add("spez", ban_reason="...")
To list the banned users along with any notes, try:
for ban in reddit.subreddit("test").banned(): print(f"{ban}: {ban.note}")
- collections() praw.models.reddit.collections.SubredditCollections
Provide an instance of
SubredditCollections
.To see the permalinks of all
Collection
s that belong to a subreddit, try:for collection in reddit.subreddit("test").collections: print(collection.permalink)
To get a specific
Collection
by its UUID or permalink, use one of the following:collection = reddit.subreddit("test").collections("some_uuid") collection = reddit.subreddit("test").collections( permalink="https://reddit.com/r/SUBREDDIT/collection/some_uuid" )
- comments() CommentHelper
Provide an instance of
CommentHelper
.For example, to output the author of the 25 most recent comments of r/test execute:
for comment in reddit.subreddit("test").comments(limit=25): print(comment.author)
- contributor() praw.models.reddit.subreddit.ContributorRelationship
Provide an instance of
ContributorRelationship
.Contributors are also known as approved submitters.
To add a contributor try:
reddit.subreddit("test").contributor.add("spez")
- controversial(*, time_filter: str = 'all', **generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for controversial items.- Parameters:
time_filter – Can be one of:
"all"
,"day"
,"hour"
,"month"
,"week"
, or"year"
(default:"all"
).- Raises:
ValueError
iftime_filter
is invalid.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").controversial(time_filter="week") reddit.multireddit(redditor="samuraisam", name="programming").controversial( time_filter="day" ) reddit.redditor("spez").controversial(time_filter="month") reddit.redditor("spez").comments.controversial(time_filter="year") reddit.redditor("spez").submissions.controversial(time_filter="all") reddit.subreddit("all").controversial(time_filter="hour")
- emoji() SubredditEmoji
Provide an instance of
SubredditEmoji
.This attribute can be used to discover all emoji for a subreddit:
for emoji in reddit.subreddit("test").emoji: print(emoji)
A single emoji can be lazily retrieved via:
reddit.subreddit("test").emoji["emoji_name"]
Note
Attempting to access attributes of a nonexistent emoji will result in a
ClientException
.
- filters() praw.models.reddit.subreddit.SubredditFilters
Provide an instance of
SubredditFilters
.For example, to add a filter, run:
reddit.subreddit("all").filters.add("test")
- flair() praw.models.reddit.subreddit.SubredditFlair
Provide an instance of
SubredditFlair
.Use this attribute for interacting with a
Subreddit
’s flair. For example, to list all the flair for a subreddit which you have theflair
moderator permission on try:for flair in reddit.subreddit("test").flair(): print(flair)
Flair templates can be interacted with through this attribute via:
for template in reddit.subreddit("test").flair.templates: print(template)
- property fullname: str
Return the object’s fullname.
A fullname is an object’s kind mapping like
t3
followed by an underscore and the object’s base36 ID, e.g.,t1_c5s96e0
.
- gilded(**generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for gilded items.Additional keyword arguments are passed in the initialization of
ListingGenerator
.For example, to get gilded items in r/test:
for item in reddit.subreddit("test").gilded(): print(item.id)
- hot(**generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for hot items.Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").hot() reddit.multireddit(redditor="samuraisam", name="programming").hot() reddit.redditor("spez").hot() reddit.redditor("spez").comments.hot() reddit.redditor("spez").submissions.hot() reddit.subreddit("all").hot()
- message(*, from_subreddit: praw.models.Subreddit | str | None = None, message: str, subject: str)
Send a message to a
Redditor
or aSubreddit
’s moderators (modmail).- Parameters:
from_subreddit –
A
Subreddit
instance or string to send the message from. When provided, messages are sent from the subreddit rather than from the authenticated user.Note
The authenticated user must be a moderator of the subreddit and have the
mail
moderator permission.message – The message content.
subject – The subject of the message.
For example, to send a private message to u/spez, try:
reddit.redditor("spez").message(subject="TEST", message="test message from PRAW")
To send a message to u/spez from the moderators of r/test try:
reddit.redditor("spez").message( subject="TEST", message="test message from r/test", from_subreddit="test" )
To send a message to the moderators of r/test, try:
reddit.subreddit("test").message(subject="TEST", message="test PM from PRAW")
- mod() praw.models.reddit.user_subreddit.UserSubredditModeration
Provide an instance of
UserSubredditModeration
.For example, to update the authenticated user’s display name:
reddit.user.me().subreddit.mod.update(title="New display name")
- moderator() praw.models.reddit.subreddit.ModeratorRelationship
Provide an instance of
ModeratorRelationship
.For example, to add a moderator try:
reddit.subreddit("test").moderator.add("spez")
To list the moderators along with their permissions try:
for moderator in reddit.subreddit("test").moderator(): print(f"{moderator}: {moderator.mod_permissions}")
- modmail() praw.models.reddit.subreddit.Modmail
Provide an instance of
Modmail
.For example, to send a new modmail from r/test to u/spez with the subject
"test"
along with a message body of"hello"
:reddit.subreddit("test").modmail.create(subject="test", body="hello", recipient="spez")
- muted() praw.models.reddit.subreddit.SubredditRelationship
Provide an instance of
SubredditRelationship
.For example, muted users can be iterated through like so:
for mute in reddit.subreddit("test").muted(): print(f"{mute}: {mute.date}")
- new(**generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for new items.Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").new() reddit.multireddit(redditor="samuraisam", name="programming").new() reddit.redditor("spez").new() reddit.redditor("spez").comments.new() reddit.redditor("spez").submissions.new() reddit.subreddit("all").new()
- classmethod parse(data: Dict[str, Any], reddit: praw.Reddit) Any
Return an instance of
cls
fromdata
.- Parameters:
data – The structured data.
reddit – An instance of
Reddit
.
- post_requirements() Dict[str, str | int | bool]
Get the post requirements for a subreddit.
- Returns:
A dict with the various requirements.
The returned dict contains the following keys:
domain_blacklist
body_restriction_policy
domain_whitelist
title_regexes
body_blacklisted_strings
body_required_strings
title_text_min_length
is_flair_required
title_text_max_length
body_regexes
link_repost_age
body_text_min_length
link_restriction_policy
body_text_max_length
title_required_strings
title_blacklisted_strings
guidelines_text
guidelines_display_policy
For example, to fetch the post requirements for r/test:
print(reddit.subreddit("test").post_requirements)
- quaran() praw.models.reddit.subreddit.SubredditQuarantine
Provide an instance of
SubredditQuarantine
.This property is named
quaran
becausequarantine
is a subreddit attribute returned by Reddit to indicate whether or not a subreddit is quarantined.To opt-in into a quarantined subreddit:
reddit.subreddit("test").quaran.opt_in()
- random() praw.models.Submission | None
Return a random
Submission
.Returns
None
on subreddits that do not support the random feature. One example, at the time of writing, is r/wallpapers.For example, to get a random submission off of r/AskReddit:
submission = reddit.subreddit("AskReddit").random() print(submission.title)
- random_rising(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Submission]
Return a
ListingGenerator
for random rising submissions.Additional keyword arguments are passed in the initialization of
ListingGenerator
.For example, to get random rising submissions for r/test:
for submission in reddit.subreddit("test").random_rising(): print(submission.title)
- rising(**generator_kwargs: str | int | Dict[str, str]) Iterator[praw.models.Submission]
Return a
ListingGenerator
for rising submissions.Additional keyword arguments are passed in the initialization of
ListingGenerator
.For example, to get rising submissions for r/test:
for submission in reddit.subreddit("test").rising(): print(submission.title)
- rules() SubredditRules
Provide an instance of
SubredditRules
.Use this attribute for interacting with a
Subreddit
’s rules.For example, to list all the rules for a subreddit:
for rule in reddit.subreddit("test").rules: print(rule)
Moderators can also add rules to the subreddit. For example, to make a rule called
"No spam"
in r/test:reddit.subreddit("test").rules.mod.add( short_name="No spam", kind="all", description="Do not spam. Spam bad" )
- search(query: str, *, sort: str = 'relevance', syntax: str = 'lucene', time_filter: str = 'all', **generator_kwargs: Any) Iterator[praw.models.Submission]
Return a
ListingGenerator
for items that matchquery
.- Parameters:
query – The query string to search for.
sort – Can be one of:
"relevance"
,"hot"
,"top"
,"new"
, or"comments"
. (default:"relevance"
).syntax – Can be one of:
"cloudsearch"
,"lucene"
, or"plain"
(default:"lucene"
).time_filter – Can be one of:
"all"
,"day"
,"hour"
,"month"
,"week"
, or"year"
(default:"all"
).
For more information on building a search query see: https://www.reddit.com/wiki/search
For example, to search all subreddits for
"praw"
try:for submission in reddit.subreddit("all").search("praw"): print(submission.title)
- sticky(*, number: int = 1) praw.models.Submission
Return a
Submission
object for a sticky of the subreddit.- Parameters:
number – Specify which sticky to return. 1 appears at the top (default:
1
).- Raises:
prawcore.NotFound
if the sticky does not exist.
For example, to get the stickied post on r/test:
reddit.subreddit("test").sticky()
- stream() praw.models.reddit.subreddit.SubredditStream
Provide an instance of
SubredditStream
.Streams can be used to indefinitely retrieve new comments made to a subreddit, like:
for comment in reddit.subreddit("test").stream.comments(): print(comment)
Additionally, new submissions can be retrieved via the stream. In the following example all submissions are fetched via the special r/all:
for submission in reddit.subreddit("all").stream.submissions(): print(submission)
- stylesheet() praw.models.reddit.subreddit.SubredditStylesheet
Provide an instance of
SubredditStylesheet
.For example, to add the css data
.test{color:blue}
to the existing stylesheet:subreddit = reddit.subreddit("test") stylesheet = subreddit.stylesheet() stylesheet.stylesheet += ".test{color:blue}" subreddit.stylesheet.update(stylesheet.stylesheet)
- submit(title: str, *, collection_id: str | None = None, discussion_type: str | None = None, draft_id: str | None = None, flair_id: str | None = None, flair_text: str | None = None, inline_media: Dict[str, praw.models.InlineMedia] | None = None, nsfw: bool = False, resubmit: bool = True, selftext: str | None = None, send_replies: bool = True, spoiler: bool = False, url: str | None = None) praw.models.Submission
Add a submission to the
Subreddit
.- Parameters:
title – The title of the submission.
collection_id – The UUID of a
Collection
to add the newly-submitted post to.discussion_type – Set to
"CHAT"
to enable live discussion instead of traditional comments (default:None
).draft_id – The ID of a draft to submit.
flair_id – The flair template to select (default:
None
).flair_text – If the template’s
flair_text_editable
value isTrue
, this value will set a custom text (default:None
).flair_id
is required whenflair_text
is provided.inline_media – A dict of
InlineMedia
objects where the key is the placeholder name inselftext
.nsfw – Whether the submission should be marked NSFW (default:
False
).resubmit – When
False
, an error will occur if the URL has already been submitted (default:True
).selftext – The Markdown formatted content for a
text
submission. Use an empty string,""
, to make a title-only submission.send_replies – When
True
, messages will be sent to the submission author when comments are made to the submission (default:True
).spoiler – Whether the submission should be marked as a spoiler (default:
False
).url – The URL for a
link
submission.
- Returns:
A
Submission
object for the newly created submission.
Either
selftext
orurl
can be provided, but not both.For example, to submit a URL to r/test do:
title = "PRAW documentation" url = "https://praw.readthedocs.io" reddit.subreddit("test").submit(title, url=url)
For example, to submit a self post with inline media do:
from praw.models import InlineGif, InlineImage, InlineVideo gif = InlineGif(path="path/to/image.gif", caption="optional caption") image = InlineImage(path="path/to/image.jpg", caption="optional caption") video = InlineVideo(path="path/to/video.mp4", caption="optional caption") selftext = "Text with a gif {gif1} an image {image1} and a video {video1} inline" media = {"gif1": gif, "image1": image, "video1": video} reddit.subreddit("test").submit("title", inline_media=media, selftext=selftext)
Note
Inserted media will have a padding of
\\n\\n
automatically added. This is due to the weirdness with Reddit’s API. Using the example above, the result selftext body will look like so:Text with a gif  an image  and video  inline
Note
To submit a post to a subreddit with the
"news"
flair, you can get the flair id like this:choices = list(subreddit.flair.link_templates.user_selectable()) template_id = next(x for x in choices if x["flair_text"] == "news")["flair_template_id"] subreddit.submit("title", flair_id=template_id, url="https://www.news.com/")
See also
submit_gallery()
to submit more than one image in the same postsubmit_image()
to submit imagessubmit_poll()
to submit pollssubmit_video()
to submit videos and videogifs
- submit_gallery(title: str, images: List[Dict[str, str]], *, collection_id: str | None = None, discussion_type: str | None = None, flair_id: str | None = None, flair_text: str | None = None, nsfw: bool = False, send_replies: bool = True, spoiler: bool = False)
Add an image gallery submission to the subreddit.
- Parameters:
title – The title of the submission.
images – The images to post in dict with the following structure:
{"image_path": "path", "caption": "caption", "outbound_url": "url"}
, onlyimage_path
is required.collection_id – The UUID of a
Collection
to add the newly-submitted post to.discussion_type – Set to
"CHAT"
to enable live discussion instead of traditional comments (default:None
).flair_id – The flair template to select (default:
None
).flair_text – If the template’s
flair_text_editable
value isTrue
, this value will set a custom text (default:None
).flair_id
is required whenflair_text
is provided.nsfw – Whether the submission should be marked NSFW (default:
False
).send_replies – When
True
, messages will be sent to the submission author when comments are made to the submission (default:True
).spoiler – Whether the submission should be marked asa spoiler (default:
False
).
- Returns:
A
Submission
object for the newly created submission.- Raises:
ClientException
ifimage_path
inimages
refers to a file that is not an image.
For example, to submit an image gallery to r/test do:
title = "My favorite pictures" image = "/path/to/image.png" image2 = "/path/to/image2.png" image3 = "/path/to/image3.png" images = [ {"image_path": image}, { "image_path": image2, "caption": "Image caption 2", }, { "image_path": image3, "caption": "Image caption 3", "outbound_url": "https://example.com/link3", }, ] reddit.subreddit("test").submit_gallery(title, images)
See also
submit()
to submit url posts and selftextssubmit_image()
to submit single imagessubmit_poll()
to submit pollssubmit_video()
to submit videos and videogifs
- submit_image(title: str, image_path: str, *, collection_id: str | None = None, discussion_type: str | None = None, flair_id: str | None = None, flair_text: str | None = None, nsfw: bool = False, resubmit: bool = True, send_replies: bool = True, spoiler: bool = False, timeout: int = 10, without_websockets: bool = False)
Add an image submission to the subreddit.
- Parameters:
collection_id – The UUID of a
Collection
to add the newly-submitted post to.discussion_type – Set to
"CHAT"
to enable live discussion instead of traditional comments (default:None
).flair_id – The flair template to select (default:
None
).flair_text – If the template’s
flair_text_editable
value isTrue
, this value will set a custom text (default:None
).flair_id
is required whenflair_text
is provided.image_path – The path to an image, to upload and post.
nsfw – Whether the submission should be marked NSFW (default:
False
).resubmit – When
False
, an error will occur if the URL has already been submitted (default:True
).send_replies – When
True
, messages will be sent to the submission author when comments are made to the submission (default:True
).spoiler – Whether the submission should be marked as a spoiler (default:
False
).timeout – Specifies a particular timeout, in seconds. Use to avoid “Websocket error” exceptions (default:
10
).title – The title of the submission.
without_websockets – Set to
True
to disable use of WebSockets (see note below for an explanation). IfTrue
, this method doesn’t return anything (default:False
).
- Returns:
A
Submission
object for the newly created submission, unlesswithout_websockets
isTrue
.- Raises:
ClientException
ifimage_path
refers to a file that is not an image.
Note
Reddit’s API uses WebSockets to respond with the link of the newly created post. If this fails, the method will raise
WebSocketException
. Occasionally, the Reddit post will still be created. More often, there is an error with the image file. If you frequently get exceptions but successfully created posts, try setting thetimeout
parameter to a value above 10.To disable the use of WebSockets, set
without_websockets=True
. This will make the method returnNone
, though the post will still be created. You may wish to do this if you are running your program in a restricted network environment, or using a proxy that doesn’t support WebSockets connections.For example, to submit an image to r/test do:
title = "My favorite picture" image = "/path/to/image.png" reddit.subreddit("test").submit_image(title, image)
See also
submit()
to submit url posts and selftextssubmit_gallery()
to submit more than one image in the same postsubmit_poll()
to submit pollssubmit_video()
to submit videos and videogifs
- submit_poll(title: str, *, collection_id: str | None = None, discussion_type: str | None = None, duration: int, flair_id: str | None = None, flair_text: str | None = None, nsfw: bool = False, options: List[str], resubmit: bool = True, selftext: str, send_replies: bool = True, spoiler: bool = False)
Add a poll submission to the subreddit.
- Parameters:
title – The title of the submission.
collection_id – The UUID of a
Collection
to add the newly-submitted post to.discussion_type – Set to
"CHAT"
to enable live discussion instead of traditional comments (default:None
).duration – The number of days the poll should accept votes, as an
int
. Valid values are between1
and7
, inclusive.flair_id – The flair template to select (default:
None
).flair_text – If the template’s
flair_text_editable
value isTrue
, this value will set a custom text (default:None
).flair_id
is required whenflair_text
is provided.nsfw – Whether the submission should be marked NSFW (default:
False
).options – A list of two to six poll options as
str
.resubmit – When
False
, an error will occur if the URL has already been submitted (default:True
).selftext – The Markdown formatted content for the submission. Use an empty string,
""
, to make a submission with no text contents.send_replies – When
True
, messages will be sent to the submission author when comments are made to the submission (default:True
).spoiler – Whether the submission should be marked as a spoiler (default:
False
).
- Returns:
A
Submission
object for the newly created submission.
For example, to submit a poll to r/test do:
title = "Do you like PRAW?" reddit.subreddit("test").submit_poll( title, selftext="", options=["Yes", "No"], duration=3 )
See also
submit()
to submit url posts and selftextssubmit_gallery()
to submit more than one image in the same postsubmit_image()
to submit single imagessubmit_video()
to submit videos and videogifs
- submit_video(title: str, video_path: str, *, collection_id: str | None = None, discussion_type: str | None = None, flair_id: str | None = None, flair_text: str | None = None, nsfw: bool = False, resubmit: bool = True, send_replies: bool = True, spoiler: bool = False, thumbnail_path: str | None = None, timeout: int = 10, videogif: bool = False, without_websockets: bool = False)
Add a video or videogif submission to the subreddit.
- Parameters:
title – The title of the submission.
video_path – The path to a video, to upload and post.
collection_id – The UUID of a
Collection
to add the newly-submitted post to.discussion_type – Set to
"CHAT"
to enable live discussion instead of traditional comments (default:None
).flair_id – The flair template to select (default:
None
).flair_text – If the template’s
flair_text_editable
value isTrue
, this value will set a custom text (default:None
).flair_id
is required whenflair_text
is provided.nsfw – Whether the submission should be marked NSFW (default:
False
).resubmit – When
False
, an error will occur if the URL has already been submitted (default:True
).send_replies – When
True
, messages will be sent to the submission author when comments are made to the submission (default:True
).spoiler – Whether the submission should be marked as a spoiler (default:
False
).thumbnail_path – The path to an image, to be uploaded and used as the thumbnail for this video. If not provided, the PRAW logo will be used as the thumbnail.
timeout – Specifies a particular timeout, in seconds. Use to avoid “Websocket error” exceptions (default:
10
).videogif – If
True
, the video is uploaded as a videogif, which is essentially a silent video (default:False
).without_websockets – Set to
True
to disable use of WebSockets (see note below for an explanation). IfTrue
, this method doesn’t return anything (default:False
).
- Returns:
A
Submission
object for the newly created submission, unlesswithout_websockets
isTrue
.- Raises:
ClientException
ifvideo_path
refers to a file that is not a video.
Note
Reddit’s API uses WebSockets to respond with the link of the newly created post. If this fails, the method will raise
WebSocketException
. Occasionally, the Reddit post will still be created. More often, there is an error with the image file. If you frequently get exceptions but successfully created posts, try setting thetimeout
parameter to a value above 10.To disable the use of WebSockets, set
without_websockets=True
. This will make the method returnNone
, though the post will still be created. You may wish to do this if you are running your program in a restricted network environment, or using a proxy that doesn’t support WebSockets connections.For example, to submit a video to r/test do:
title = "My favorite movie" video = "/path/to/video.mp4" reddit.subreddit("test").submit_video(title, video)
See also
submit()
to submit url posts and selftextssubmit_image()
to submit imagessubmit_gallery()
to submit more than one image in the same postsubmit_poll()
to submit polls
- subscribe(*, other_subreddits: List[praw.models.Subreddit] | None = None)
Subscribe to the subreddit.
- Parameters:
other_subreddits – When provided, also subscribe to the provided list of subreddits.
For example, to subscribe to r/test:
reddit.subreddit("test").subscribe()
- top(*, time_filter: str = 'all', **generator_kwargs: str | int | Dict[str, str]) Iterator[Any]
Return a
ListingGenerator
for top items.- Parameters:
time_filter – Can be one of:
"all"
,"day"
,"hour"
,"month"
,"week"
, or"year"
(default:"all"
).- Raises:
ValueError
iftime_filter
is invalid.
Additional keyword arguments are passed in the initialization of
ListingGenerator
.This method can be used like:
reddit.domain("imgur.com").top(time_filter="week") reddit.multireddit(redditor="samuraisam", name="programming").top(time_filter="day") reddit.redditor("spez").top(time_filter="month") reddit.redditor("spez").comments.top(time_filter="year") reddit.redditor("spez").submissions.top(time_filter="all") reddit.subreddit("all").top(time_filter="hour")
- traffic() Dict[str, List[List[int]]]
Return a dictionary of the
Subreddit
’s traffic statistics.- Raises:
prawcore.NotFound
when the traffic stats aren’t available to the authenticated user, that is, they are not public and the authenticated user is not a moderator of the subreddit.
The traffic method returns a dict with three keys. The keys are
day
,hour
andmonth
. Each key contains a list of lists with 3 or 4 values. The first value is a timestamp indicating the start of the category (start of the day for theday
key, start of the hour for thehour
key, etc.). The second, third, and fourth values indicate the unique pageviews, total pageviews, and subscribers, respectively.Note
The
hour
key does not contain subscribers, and therefore each sub-list contains three values.For example, to get the traffic stats for r/test:
stats = reddit.subreddit("test").traffic()
- unsubscribe(*, other_subreddits: List[praw.models.Subreddit] | None = None)
Unsubscribe from the subreddit.
- Parameters:
other_subreddits – When provided, also unsubscribe from the provided list of subreddits.
To unsubscribe from r/test:
reddit.subreddit("test").unsubscribe()
- widgets() praw.models.SubredditWidgets
Provide an instance of
SubredditWidgets
.Example usage
Get all sidebar widgets:
for widget in reddit.subreddit("test").widgets.sidebar: print(widget)
Get ID card widget:
print(reddit.subreddit("test").widgets.id_card)
- wiki() praw.models.reddit.subreddit.SubredditWiki
Provide an instance of
SubredditWiki
.This attribute can be used to discover all wikipages for a subreddit:
for wikipage in reddit.subreddit("test").wiki: print(wikipage)
To fetch the content for a given wikipage try:
wikipage = reddit.subreddit("test").wiki["proof"] print(wikipage.content_md)
Util
- class praw.models.util.BoundedSet(max_items: int)
A set with a maximum size that evicts the oldest items when necessary.
This class does not implement the complete set interface.
- __contains__(item: Any) bool
Test if the
BoundedSet
contains item.
- __init__(max_items: int)
Initialize a
BoundedSet
instance.
- class praw.models.util.ExponentialCounter(max_counter: int)
A class to provide an exponential counter with jitter.
- __init__(max_counter: int)
Initialize an
ExponentialCounter
instance.- Parameters:
max_counter –
The maximum base value.
Note
The computed value may be 3.125% higher due to jitter.
- reset()
Reset the counter to 1.
- praw.models.util.permissions_string(*, known_permissions: Set[str], permissions: List[str] | None) str
Return a comma separated string of permission changes.
- Parameters:
known_permissions – A set of strings representing the available permissions.
permissions – A list of strings, or
None
. These strings can exclusively contain+
or-
prefixes, or contain no prefixes at all. When prefixed, the resulting string will simply be the joining of these inputs. When not prefixed, all permissions are considered to be additions, and all permissions in theknown_permissions
set that aren’t provided are considered to be removals. WhenNone
, the result is"+all"
.
- praw.models.util.stream_generator(function: Callable, *, attribute_name: str = 'fullname', exclude_before: bool = False, pause_after: int | None = None, skip_existing: bool = False, **function_kwargs: Any) Generator[Any, None, None]
Yield new items from
function
as they become available.- Parameters:
function – A callable that returns a
ListingGenerator
, e.g.,Subreddit.comments()
orSubreddit.new()
.attribute_name – The field to use as an ID (default:
"fullname"
).exclude_before – When
True
does not passparams
tofunction
(default:False
).pause_after – An integer representing the number of requests that result in no new items before this function yields
None
, effectively introducing a pause into the stream. A negative value yieldsNone
after items from a single response have been yielded, regardless of number of new items obtained in that response. A value of0
yieldsNone
after every response resulting in no new items, and a value ofNone
never introduces a pause (default:None
).skip_existing – When
True
, this does not yield any results from the first request thereby skipping any items that existed in the stream prior to starting the stream (default:False
).
Additional keyword arguments will be passed to
function
.Note
This function internally uses an exponential delay with jitter between subsequent responses that contain no new results, up to a maximum delay of just over 16 seconds. In practice, that means that the time before pause for
pause_after=N+1
is approximately twice the time before pause forpause_after=N
.For example, to create a stream of comment replies, try:
reply_function = reddit.inbox.comment_replies for reply in praw.models.util.stream_generator(reply_function): print(reply)
To pause a comment stream after six responses with no new comments, try:
subreddit = reddit.subreddit("test") for comment in subreddit.stream.comments(pause_after=6): if comment is None: break print(comment)
To resume fetching comments after a pause, try:
subreddit = reddit.subreddit("test") comment_stream = subreddit.stream.comments(pause_after=5) for comment in comment_stream: if comment is None: break print(comment) # Do any other processing, then try to fetch more data for comment in comment_stream: if comment is None: break print(comment)
To bypass the internal exponential backoff, try the following. This approach is useful if you are monitoring a subreddit with infrequent activity, and you want to consistently learn about new items from the stream as soon as possible, rather than up to a delay of just over sixteen seconds.
subreddit = reddit.subreddit("test") for comment in subreddit.stream.comments(pause_after=0): if comment is None: continue print(comment)
Working with Refresh Tokens
Reddit OAuth2 Scopes
Before working with refresh tokens you should decide which scopes your application
requires. If you want to use all scopes, you can use the special scope *
.
To get an up-to-date listing of all Reddit scopes and their descriptions run the following:
import requests
response = requests.get(
"https://www.reddit.com/api/v1/scopes.json",
headers={"User-Agent": "fetch-scopes by u/bboe"},
)
for scope, data in sorted(response.json().items()):
print(f"{scope:>18s} {data['description']}")
As of February 2021, the available scopes are:
Scope |
Description |
---|---|
account |
Update preferences and related account information. Will not have access to your email or password. |
creddits |
Spend my reddit gold creddits on giving gold to other users. |
edit |
Edit and delete my comments and submissions. |
flair |
Select my subreddit flair. Change link flair on my submissions. |
history |
Access my voting history and comments or submissions I’ve saved or hidden. |
identity |
Access my reddit username and signup date. |
livemanage |
Manage settings and contributors of live threads I contribute to. |
modconfig |
Manage the configuration, sidebar, and CSS of subreddits I moderate. |
modcontributors |
Add/remove users to approved user lists and ban/unban or mute/unmute users from subreddits I moderate. |
modflair |
Manage and assign flair in subreddits I moderate. |
modlog |
Access the moderation log in subreddits I moderate. |
modmail |
Access and manage modmail via mod.reddit.com. |
modothers |
Invite or remove other moderators from subreddits I moderate. |
modposts |
Approve, remove, mark nsfw, and distinguish content in subreddits I moderate. |
modself |
Accept invitations to moderate a subreddit. Remove myself as a moderator or contributor of subreddits I moderate or contribute to. |
modtraffic |
Access traffic stats in subreddits I moderate. |
modwiki |
Change editors and visibility of wiki pages in subreddits I moderate. |
mysubreddits |
Access the list of subreddits I moderate, contribute to, and subscribe to. |
privatemessages |
Access my inbox and send private messages to other users. |
read |
Access posts and comments through my account. |
report |
Report content for rules violations. Hide & show individual submissions. |
save |
Save and unsave comments and submissions. |
structuredstyles |
Edit structured styles for a subreddit I moderate. |
submit |
Submit links and comments from my account. |
subscribe |
Manage my subreddit subscriptions. Manage “friends” - users whose content I follow. |
vote |
Submit and change my votes on comments and submissions. |
wikiedit |
Edit wiki pages on my behalf |
wikiread |
Read wiki pages through my account |
Obtaining Refresh Tokens
The following program can be used to obtain a refresh token with the desired scopes:
#!/usr/bin/env python
"""This example demonstrates the flow for retrieving a refresh token.
This tool can be used to conveniently create refresh tokens for later use with your web
application OAuth2 credentials.
To create a Reddit application visit the following link while logged into the account
you want to create a refresh token for: https://www.reddit.com/prefs/apps/
Create a "web app" with the redirect uri set to: http://localhost:8080
After the application is created, take note of:
- REDDIT_CLIENT_ID; the line just under "web app" in the upper left of the Reddit
Application
- REDDIT_CLIENT_SECRET; the value to the right of "secret"
Usage:
EXPORT praw_client_id=<REDDIT_CLIENT_ID>
EXPORT praw_client_secret=<REDDIT_CLIENT_SECRET>
python3 obtain_refresh_token.py
"""
import random
import socket
import sys
import praw
def main():
"""Provide the program's entry point when directly executed."""
scope_input = input(
"Enter a comma separated list of scopes, or '*' for all scopes: "
)
scopes = [scope.strip() for scope in scope_input.strip().split(",")]
reddit = praw.Reddit(
redirect_uri="http://localhost:8080",
user_agent="obtain_refresh_token/v0 by u/bboe",
)
state = str(random.randint(0, 65000))
url = reddit.auth.url(duration="permanent", scopes=scopes, state=state)
print(f"Now open this url in your browser: {url}")
client = receive_connection()
data = client.recv(1024).decode("utf-8")
param_tokens = data.split(" ", 2)[1].split("?", 1)[1].split("&")
params = {
key: value for (key, value) in [token.split("=") for token in param_tokens]
}
if state != params["state"]:
send_message(
client,
f"State mismatch. Expected: {state} Received: {params['state']}",
)
return 1
elif "error" in params:
send_message(client, params["error"])
return 1
refresh_token = reddit.auth.authorize(params["code"])
send_message(client, f"Refresh token: {refresh_token}")
return 0
def receive_connection():
"""Wait for and then return a connected socket..
Opens a TCP connection on port 8080, and waits for a single client.
"""
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(("localhost", 8080))
server.listen(1)
client = server.accept()[0]
server.close()
return client
def send_message(client, message):
"""Send message to client and close the connection."""
print(message)
client.send(f"HTTP/1.1 200 OK\r\n\r\n{message}".encode("utf-8"))
client.close()
if __name__ == "__main__":
sys.exit(main())
This script assumes you have configured your application’s redirect uri
to
localhost:8080
When you execute this script interactively:
You will be prompted to provide a comma-separated list of scopes.
You will be given a URL that will take you through the auth flow on Reddit.
When you open the provided link in your browser, Reddit will ask you for permission to grant the application permissions to the scopes requested.
After clicking allow, you will have a new authorized application configured.
You will be redirected to another page (the application’s
redirect uri
) where your refresh token will be displayed and will be printed to the command line.
You only have to run this script once for each refresh token. The refresh token (along
with the application’s client_id
, client_secret
) are valid credentials until
manually revoked by the user.
Submission Stream Reply Bot
Most redditors have seen bots in action on the site. Reddit bots can perform a number of tasks including providing useful information, e.g., an Imperial to Metric units bot; convenience, e.g., a link corrector bot; or analytical information, e.g., redditor analyzer bot for writing complexity.
PRAW provides a simple way to build your own bot using the Python programming language. As a result, it is little surprise that a majority of bots on Reddit are powered by PRAW.
This tutorial will show you how to build a bot that monitors a particular subreddit, r/AskReddit, for new submissions containing simple questions and replies with an appropriate link to lmgtfy (Let Me Google That For You).
There are three key components we will address to perform this task:
Monitor new submissions.
Analyze the title of each submission to see if it contains a simple question.
Reply with an appropriate lmgtfy link.
LMGTFY Bot
The goal of the LMGTFY Bot is to point users in the right direction when they ask a simple question that is unlikely to be upvoted or answered by other users.
Two examples of such questions are:
“What is the capital of Canada?”
“How many feet are in a yard?”
Once we identify these questions, the LMGTFY Bot will reply to the submission with an appropriate lmgtfy link. For the example questions those links are:
Step 1: Getting Started
Access to Reddit’s API requires a set of OAuth2 credentials. Those credentials are obtained by registering an application with Reddit. To register an application and receive a set of OAuth2 credentials please follow only the “First Steps” section of Reddit’s OAuth2 Quick Start Example wiki page.
Once the credentials are obtained we can begin writing the LMGTFY Bot. Start by creating
an instance of Reddit
:
import praw
reddit = praw.Reddit(
client_id="CLIENT_ID",
client_secret="CLIENT_SECRET",
password="PASSWORD",
user_agent="LMGTFY (by u/USERNAME)",
username="USERNAME",
)
In addition to the OAuth2 credentials, the username and password of the Reddit account that registered the application are required.
Note
This example demonstrates use of a script type application. For other application types please see Reddit’s wiki page OAuth2 App Types.
Step 2: Monitoring New Submissions to r/AskReddit
PRAW provides a convenient way to obtain new submissions to a given subreddit. To indefinitely iterate over new submissions to a subreddit add:
subreddit = reddit.subreddit("AskReddit")
for submission in subreddit.stream.submissions():
# do something with submission
...
Replace "AskReddit"
with the name of another subreddit if you want to iterate
through its new submissions. Additionally, multiple subreddits can be specified by
joining them with pluses (+
), for example "AskReddit+NoStupidQuestions"
. All
subreddits can be specified using the special name "all"
. Subreddits can be excluded
from the special "all"
subreddit by joining them with minuses (-
), for example
"all-excluded_subreddit1-excluded_subreddit2"
.
Step 3: Analyzing the Submission Titles
Now that we have a stream of new submissions to r/AskReddit, it is time to see if their titles contain a simple question. We naïvely define a simple question as:
It must contain no more than ten words.
It must contain one of the phrases
"what is"
,"what are"
, or"who is"
.
Warning
These naïve criteria result in many false positives. It is strongly recommended that you develop more precise heuristics before launching a bot on any popular subreddits.
First we filter out titles that contain more than ten words:
if len(submission.title.split()) > 10:
return
We then check to see if the submission’s title contains any of the desired phrases:
questions = ["what is", "who is", "what are"]
normalized_title = submission.title.lower()
for question_phrase in questions:
if question_phrase in normalized_title:
# do something with a matched submission
break
String comparison in Python is case sensitive. As a result, we only compare a normalized version of the title to our lower-case question phrases. In this case, “normalized” means only lower-case.
The break
at the end prevents us from matching more than once on a single
submission. For instance, what would happen without the break
if a submission’s
title was “Who is or what are buffalo?”?
Step 4: Automatically Replying to the Submission
The LMGTFY Bot is nearly complete. We iterate through submissions and find ones that appear to be simple questions. All that is remaining is to reply to those submissions with an appropriate lmgtfy link.
First we will need to construct a working lmgtfy link. In essence, we want to pass the
entire submission title to lmgtfy. However, there are certain characters that are not
permitted in URLs or have other meanings. For instance, the space character, `` , is
not permitted, and the question mark, ``?
, has a special meaning. Thus we will
transform those into their URL-safe representation so that a question like “What is the
capital of Canada?” is transformed into the link
https://lmgtfy.com/?q=What+is+the+capital+of+Canada%3F
.
There are a number of ways we could accomplish this task. For starters, we could write a
function to replace spaces with pluses (+
) and question marks with %3F
. However,
there is even an easier way; using an existing built-in function to do so.
Add the following code where the “do something with a matched submission” comment is located:
from urllib.parse import quote_plus
reply_template = "[Let me google that for you](https://lmgtfy.com/?q={})"
url_title = quote_plus(submission.title)
reply_text = reply_template.format(url_title)
Now that we have the reply text, replying to the submission is easy:
submission.reply(reply_text)
If all went well, your comment should have been made. If your bot account is brand new, you will likely run into rate limit issues. These rate limits will persist until that account acquires sufficient karma.
Step 5: Cleaning Up The Code
While we have a working bot, we have added little segments here and there. If we were to continue to do so in this fashion our code would be quite unreadable. Let’s clean it up some.
The first thing we should do is put all of our import statements at the top of the file. It is common to list built-in packages before third-party ones:
#!/usr/bin/env python3
from urllib.parse import quote_plus
import praw
Next, we extract a few constants that are used in our script:
QUESTIONS = ["what is", "who is", "what are"]
REPLY_TEMPLATE = "[Let me google that for you](https://lmgtfy.com/?q={})"
We then extract the segment of code pertaining to processing a single submission into its own function:
def process_submission(submission):
# Ignore titles with more than 10 words as they probably are not simple questions.
if len(submission.title.split()) > 10:
return
normalized_title = submission.title.lower()
for question_phrase in QUESTIONS:
if question_phrase in normalized_title:
url_title = quote_plus(submission.title)
reply_text = REPLY_TEMPLATE.format(url_title)
print(f"Replying to: {submission.title}")
submission.reply(reply_text)
# A reply has been made so do not attempt to match other phrases.
break
Observe that we added some comments and a print()
call. The print()
addition informs us every time we are about to reply to a submission, which is useful to
ensure the script is running.
Next, it is a good practice to not have any top-level executable code in case you want
to turn your Python script into a Python module, i.e., import it from another Python
script or module. A common way to do that is to move the top-level code to a main
function:
def main():
reddit = praw.Reddit(
client_id="CLIENT_ID",
client_secret="CLIENT_SECRET",
password="PASSWORD",
user_agent="LMGTFY (by u/USERNAME)",
username="USERNAME",
)
subreddit = reddit.subreddit("AskReddit")
for submission in subreddit.stream.submissions():
process_submission(submission)
Finally, we need to call main
only in the cases that this script is the one being
executed:
if __name__ == "__main__":
main()
The Complete LMGTFY Bot
The following is the complete LMGTFY Bot:
#!/usr/bin/env python3
from urllib.parse import quote_plus
import praw
QUESTIONS = ["what is", "who is", "what are"]
REPLY_TEMPLATE = "[Let me google that for you](https://lmgtfy.com/?q={})"
def main():
reddit = praw.Reddit(
client_id="CLIENT_ID",
client_secret="CLIENT_SECRET",
password="PASSWORD",
user_agent="LMGTFY (by u/USERNAME)",
username="USERNAME",
)
subreddit = reddit.subreddit("AskReddit")
for submission in subreddit.stream.submissions():
process_submission(submission)
def process_submission(submission):
# Ignore titles with more than 10 words as they probably are not simple questions.
if len(submission.title.split()) > 10:
return
normalized_title = submission.title.lower()
for question_phrase in QUESTIONS:
if question_phrase in normalized_title:
url_title = quote_plus(submission.title)
reply_text = REPLY_TEMPLATE.format(url_title)
print(f"Replying to: {submission.title}")
submission.reply(reply_text)
# A reply has been made so do not attempt to match other phrases.
break
if __name__ == "__main__":
main()
Change Log
PRAW follows semantic versioning.
7.7.0 (2023/02/25)
Added
delete_mobile_banner()
to delete mobile banners.upload_mobile_banner()
to upload mobile banners.
Fixed
An issue with iterating
ModNote
when a user has more than a hundred notes.Removal reasons are now returned in the same order as they appear on Reddit.
7.6.1 (2022/11/11)
Changed
Revert
edit()
positional argument deprecation.Revert
reply()
positional argument deprecation.Revert
reply()
positional argument deprecation.Revert
edit()
positional argument deprecation.Revert
reply()
positional argument deprecation.
Fixed
An issue where
ModmailConversation
’smessages
attribute would only contain the latest message.
7.6.0 (2022/05/10)
Added
pin()
to manage pinned submissions on the authenticated user’s profile.update_display_layout()
to update the display layout of posts in aCollection
.SubredditCollectionsModeration.create()
keyword argumentdisplay_layout
for specifying a display layout when creating aCollection
.ModNote
to represent a moderator note.ModNote.delete()
to delete a single moderator note.RedditModNotes
to interact with moderator notes from aReddit
instance. This provides the ability to create and fetch notes for one or more redditors from one or more subreddits.RedditorModNotes
to interact with moderator notes from aRedditor
instance.RedditorModNotes.subreddits()
to obtain moderator notes from multiple subreddits for a single redditor.SubredditModNotes
to interact with moderator notes from aSubreddit
instance.SubredditModNotes.redditors()
to obtain moderator notes for multiple redditors from a single subreddit.create()
to create a moderator note.Redditor.notes
to interact withRedditorModNotes
.SubredditModeration.notes
to interact withSubredditModNotes
.create_note()
create a moderator note from aComment
orSubmission
.author_notes()
to view the moderator notes for the author of aComment
orSubmission
.
Changed
Drop support for Python 3.6, which is end-of-life on 2021-12-23.
conversations()
now returns aListingGenerator
allowing you to page through more than 100 conversations.
Deprecated
The
after
argument forconversations()
will now have to be included inparams
keyword argument.Positional keyword arguments for applicable functions and methods. Starting with PRAW 8, most functions and methods will no longer support positional arguments. It will encourage more explicit argument passing, enable arguments to be sorted alphabetically, and prevent breaking changes when adding new arguments to existing methods.
7.5.0 (2021/11/13)
Added
Log a warning if a submission’s
comment_sort
attribute is updated after the submission has already been fetched and awarn_comment_sort
config setting to turn off the warning.user_selectable()
to get available subreddit link flairs.Automatic RateLimit handling will support errors with millisecond resolution.
Fixed
An import error when using PRAW in environments where
libsqlite3-dev
is needed to utilize thesqlite3
builtin.Fixed bug where some keyword arguments that are passed to
Draft.submit()
would not have an effect.
7.4.0 (2021/07/30)
Added
discussions()
to obtain site-wide link submissions that link to the WikiPage.revert()
to revert a WikiPage to a specified revision.Inbox.mark_all_read()
to mark all messages as read with one API call.unblock_subreddit()
to unblock a subreddit.update_crowd_control_level()
to update the crowd control level of a post.moderator_subreddits()
, which returns information about the subreddits that the authenticated user moderates, has been restored.The configuration setting
refresh_token
has been added back. See https://www.reddit.com/r/redditdev/comments/olk5e6/followup_oauth2_api_changes_regarding_refresh/ for more info.Draft
to represent a submission draft.Draft.delete()
to delete drafts.Draft.submit()
to submit drafts.Draft.update()
to modify drafts.DraftHelper
to fetch or create drafts on new Reddit.
Changed
Reddit.delete()
now accepts theparams
parameter.
Deprecated
Reddit
keyword argumenttoken_manager
.
7.3.0 (2021/06/17)
Added
UserSubreddit
for thesubreddit
attribute ofRedditor
.username_available()
checks if a username is available.trusted()
to retrieve aRedditorList
of trusted users.trust()
to add a user to the trusted list.distrust()
to remove a user from the trusted list.SQLiteTokenManager
(may not work on Windows).
Changed
moderated()
will now objectify all data returned from the API.The
wiki_edit
endpoint has been changed fromr/{subreddit}/api/wiki/edit/
tor/{subreddit}/api/wiki/edit
.Redditor.block()
no longer needs to retrieve a user’s fullname.
Deprecated
The
subreddit
attribute ofRedditor
is no longer a dict.Legacy modmail is slated for deprecation by Reddit in June 2021. See https://www.reddit.com/r/modnews/comments/mar9ha/even_more_modmail_improvements/ for more info.
Fixed
Fixed bug where
WikiPage.edit()
andSubredditWiki.create()
would fail if passedcontent
andreason
parameters that produced a request with a body greater than 500 KiB, even when the parameters did not exceed their respective permitted maximum lengths.Fixed bug where
request()
could not handle instances ofBadRequest
s when the JSON data contained only the keys “reason” and “message”.Fixed bug where
request()
could not handle instances ofBadRequest
s when the response did not contain valid JSON data.Fixed bug where
fullname()
sometimes returned the wrong fullname.
7.2.0 (2021/02/24)
Added
Reddit
keyword argumenttoken_manager
.FileTokenManager
and its parent abstract classBaseTokenManager
.
Deprecated
The configuration setting
refresh_token
is deprecated and its use will result in aDeprecationWarning
. This deprecation applies in all ways of setting configuration values, i.e., viapraw.ini
, as a keyword argument when initializing an instance ofReddit
, and via thePRAW_REFRESH_TOKEN
environment variable. To be prepared for PRAW 8, use the newReddit
keyword argumenttoken_manager
. See Working with Refresh Tokens in PRAW’s documentation for an example.me()
will no longer returnNone
when called inread_only
mode starting in PRAW 8. ADeprecationWarning
will be issued. To switch forward to the PRAW 8 behavior setpraw8_raise_exception_on_me=True
in yourReddit
call.
7.1.4 (2021/02/07)
Fixed
Asynchronous check will no longer fail in Python 3.6 multithreading edge cases.
7.1.3 (2021/02/05)
Changed
Asynchronous check will no longer occur when in a Jupyter notebook.
7.1.2 (2021/02/03)
Fixed
Asynchronous check would not work on Python 3.6 as
get_running_loop()
only exists on Python 3.7+.
7.1.1 (2021/02/02)
Added
Add method
Subreddits.premium()
to reflect the naming change in Reddit’s API.Ability to submit image galleries with
submit_gallery()
.Ability to pass a gallery url to
Reddit.submission()
.Ability to specify modmail mute duration.
Add method
invited()
to get invited moderators of a subreddit.Ability to submit text/self posts with inline media.
Add method
Submission.award()
andComment.award()
with the ability to specify type of award, anonymity, and message when awarding a submission or comment.Ability to specify subreddits by name using the subreddits parameter in
Reddit.info()
.A check to see if PRAW is running in an asynchronous environment and will advise the user to use Async PRAW. This also adds a configuration option to disable the check.
Changed
Drop support for Python 3.5, which is end-of-life on 2020-09-13.
BoundedSet
will now utilize a Last-Recently-Used (LRU) storing mechanism, which will change the order in which elements are removed from the set.Improved
submit_image()
andsubmit_video()
performance in slow network environments by removing a race condition when establishing a websocket connection.
Deprecated
Subreddits.gold()
is superseded bySubreddits.premium()
.Submission.gild()
is superseded bySubmission.award()
.Comment.gild()
is superseded byComment.award()
.
Fixed
An issue where leaving as a moderator fails if you are using token auth.
An issue where an incorrect error was being raised due to invalid submission urls.
Some cases where streams yield the same item multiple times. This cannot be prevented in every case.
7.1.0 (2020/06/22)
Added
Rule
to represent one rule of a subreddit.SubredditRules
to get and add rules.Ability to submit polls with
submit_poll()
.PollData
andPollOption
.Ability to view poll data and poll options via the
.poll_data
attribute on poll submissions.Add method
delete()
toReddit
class to support HTTP DELETE requests.Added
CalendarConfiguration
to represent the configuration of aCalendar
widget.Added
Styles
to represent widget styling information.Ability to stream live thread updates via new class
LiveThreadStream
with methodupdates()
.
Changed
RemovalReason.update()
’s parameters are now optional.SubredditRemovalReasons.__getitem__()
now takes integers and slices to get removal reasons from the list of reasons as returned by Reddit.
Deprecated
WebSocketException.original_exception
is deprecated and slated for removal in PRAW 8.0.
Fixed
An issue where certain subreddit settings could not be set through
SubredditModeration.update()
, such aswelcome_message_enabled
andwelcome_message_text
. This change also removes the need for PRAW to track current subreddit settings and send unmodified ones in the update request.Instances of
BadRequest
s captured by PRAW that do not contain any detailed JSON data are re-raised as the originalBadRequest
.submit_image()
andsubmit_video()
will throwMediaPostFailed
when Reddit fails to post an image or video post.
7.0.0 (2020/04/24)
Added
config_interpolation
parameter forReddit
supporting basic and extended modes.Add
partial_redditors()
that returns lightweight redditor objects that contain only a few fields. This is useful for resolvingRedditor
IDs to their usernames in bulk.User.friends()
has a new parameteruser
that takes either an instance ofRedditor
or a string containing a redditor name and returns an instance ofRedditor
if the authenticated user is friends with the user, otherwise throws an exception.SubmissionModeration.flair()
has the parameterflair_template_id
for applying flairs with template IDs.Emoji.update()
supports modifying an emoji’s permissions.SubredditEmoji.add()
now supports optionally passing booleans to set an emoji’s permissions upon upload.Methods
SubredditLinkFlairTemplates.update()
andSubredditRedditorFlairTemplates.update()
contain a new parameter,fetch
, that toggles the automatic fetching of existing data from Reddit. It is set to True by default.Values in methods
SubredditLinkFlairTemplates.update()
andSubredditRedditorFlairTemplates.update()
that are left as the defaults will no longer be over-written if thefetch
parameter is set toTrue
, but will fill in existing values for the flair template.The parameter
text
for methodsSubredditLinkFlairTemplates.update()
andSubredditRedditorFlairTemplates.update()
is no longer required.There is a new method,
post_requirements()
, to fetch a subreddit’s post requirements.Method
SubmissionModeration.sticky()
will now ignore the Conflict exception generated by trying to sticky the same post multiple times.A new method
CommentModeration.show()
will uncollapse a comment that was collapsed because of Crowd ControlMethods
submit_image()
andsubmit_video()
will throwTooLargeMediaException
if the submitted media is rejected by Reddit due to the size of the media.Class
Reddit
has an attribute,validate_on_submit
, that can be set after class initialization that causes methodssubmit()
,submit_image()
,submit_video()
, andSubmission.edit()
to check that the submission matches a subreddit’s post validation rules. This attribute will be functionally useless once Reddit implements their change. This attribute will be deprecated on the next release after Reddit’s change, and will be removed on the next major release after Reddit’s change.
Warning
In May-June 2020, Reddit will force all submissions to run through a subreddit’s validation rules.
Introduced a data class,
RedditErrorItem
, to represent an individual error item returned from Reddit.Class
RedditAPIException
now serves as a container for theRedditErrorItem
s. You can access the items by doingRedditAPIException.items
, which returns a list.APIException
is an alias toRedditAPIException
.Parameter
discussion_type
to methodssubmit()
,submit_image()
, andsubmit_video()
to support submitting as a live discussion (set to"CHAT"
).Instances of
Trophy
can be compared for equality with each other.Reddit
has a new configurable parameter,timeout
. This defaults to 16 seconds. It controls how long PRAW will wait for a response before throwing an exception.PRAW now handles ratelimit errors returned as instances of
RedditAPIException
.Reddit
has one new parameter,ratelimit_seconds
. The parameter configures the maximum amount of seconds to catch ratelimits for. It defaults to 5 seconds when not specified.
Changed
prawcore.BadRequest
should no longer be raised. Instead, a more usefulRedditAPIException
instance will be raised.Set the default comment sort to
confidence
instead ofbest
because it turns outbest
isn’t actually the correct value for the parameter.
Deprecated
APIException
is deprecated and slated for removal in PRAW 8.0.
Fixed
SubredditFlair.update()
will not error out when the flair text contains quote marks.
Removed
Converting
APIException
to string will no longer escape unicode characters.Module
praw.models.modaction
no longer exists. Please use the modulepraw.models.mod_action
, or directly importModAction
frompraw.models
.Methods
SubredditLinkFlairTemplates.update()
andSubredditRedditorFlairTemplates.update()
will no longer create flairs that are using an invalid template id, but instead throw aInvalidFlairTemplateID
.Method
reddit.user.moderator_subreddits
has been removed. Please usemoderated()
instead.
6.5.1 (2020/01/07)
Fixed
Removed usages of
NoReturn
that caused PRAW to fail due toImportError
in Python<3.5.4
and<3.6.2
.
6.5.0 (2020/01/05)
Added
set_original_content()
supports marking a submission as original content.unset_original_content()
supports unmarking a submission as original content.moderated()
to get a list of a redditor’s moderated subreddits.Parameter
without_websockets
tosubmit_image()
andsubmit_video()
to submit without using WebSockets.Reddit.redditor()
supportsfullname
param to fetch aRedditor
by the fullname instead of name.Redditor
constructor now also hasfullname
param.Add
RemovalReason
andSubredditRemovalReasons
to work with removal reasonsAttribute
removal_reasons
toSubredditModeration
to interact with new removal reason classesParameters
mod_note
andreason_id
toremove()
to optionally apply a removal reason on removalAdd
SubredditModerationStream
to enable moderation streamsAttribute
stream
toSubredditModeration
to interact with new moderation streamsAdd
edited()
to allow streaming ofSubredditModeration.edited()
Add
log()
to allow streaming ofSubredditModeration.log()
Add
modmail_conversations()
to allow streaming ofModmail.conversations()
Add
modqueue()
to allow streaming ofSubredditModeration.modqueue()
Add
reports()
to allow streaming ofSubredditModeration.reports()
Add
spam()
to allow streaming ofSubredditModeration.spam()
Add
unmoderated()
to allow streaming ofSubredditModeration.unmoderated()
Add
unread()
to allow streaming ofSubredditModeration.unread()
Parameter
exclude_before
tostream_generator()
to allowmodmail_conversations()
to workParameters
allowable_content
andmax_emojis
toadd()
,add()
, andupdate()
, as well as its child classes.
Deprecated
Method
reddit.user.moderator_subreddits
asmoderated()
provides more functionality.The file for ModActions (
praw/models/modaction.py
) has been moved topraw/models/mod_action.py
and the previous has been deprecated.
Expected Changes
The behavior of
APIException
will no longer unicode-escape strings in the next minor release.
6.4.0 (2019/09/21)
Added
crosspost()
support parameterflair_id
to flair the submission immediately upon crossposting.crosspost()
support parameterflair_text
to set a custom text to the flair immediately upon crossposting.crosspost()
support parameternsfw
to mark the submission NSFW immediately upon crossposting.crosspost()
support parameterspoiler
to mark the submission as a spoiler immediately upon crossposting.
Fixed
add_community_list()
has parameterdescription
to support unannounced upstream Reddit API changes.WidgetModeration.update()
supports passing a list ofSubreddit
objects.
Changed
Removed
css_class
parameter cannot be used withbackground_color
,text_color
, ormod_only
constraint on methods:SubredditFlairTemplates.update()
SubredditRedditorFlairTemplates.add()
SubredditLinkFlairTemplates.add()
Removed
Drop official support for Python 2.7.
Multireddit.rename()
no longer works due to a change in the Reddit API.
6.3.1 (2019/06/10)
Removed
SubredditListingMixin.gilded()
, as this was supposed to be removed in 6.0.0 after deprecation in 5.2.0.
6.3.0 (2019/06/09)
Added
Collections (
Collection
and helper classes).submit()
,submit_image()
, andsubmit_video()
can be used to submit a post directly to a collection.praw.util.camel_to_snake
andpraw.util.snake_case_keys
.Comments can now be locked and unlocked via
comment.mod.lock()
andcomment.mod.unlock()
. See: (lock()
andunlock()
).align
parameter toupload_banner_additional_image()
Changed
Reddit.info()
now accepts any non-str iterable for fullnames (not justlist
).Reddit.info()
now returns a generator instead of a list when using theurl
parameter.
6.2.0 (2019/05/05)
Added
submit()
,submit_image()
, andsubmit_video()
support parameternsfw
to mark the submission NSFW immediately upon posting.submit()
,submit_image()
, andsubmit_video()
support parameterspoiler
to mark the submission as a spoiler immediately upon posting.submit_image()
andsubmit_video()
support parametertimeout
. Default timeout has been raised from 2 seconds to 10 seconds.Added parameter
function_kwargs
tostream_generator()
to pass additional kwargs tofunction
.
Fixed
Subreddit.random()
returnsNone
instead of raisingClientException
when the subreddit does not support generating random submissions.
Other
Bumped minimum prawcore version to 1.0.1.
6.1.1 (2019/01/29)
Added
SubredditFlair.set()
supports parameterflair_template_id
for giving a user redesign flair.
6.1.0 (2019/01/19)
Added
Add method
Redditor.trophies()
to get a list of the Redditor’s trophies.Add class
PostFlairWidget
.Add attributes
reply_limit
andreply_sort
to classComment
Add class
SubredditWidgetsModeration
(accessible throughSubredditWidgets.mod
) and methodadd_text_area()
.Add class
WidgetModeration
(accessible through the.mod
attribute on any widget) with methodsupdate()
anddelete()
.Add method
Reddit.put()
for HTTP PUT requests.Add methods
add_calendar()
andadd_community_list()
.Add methods
add_image_widget()
andupload_image()
.Add method
add_custom_widget()
.Add method
add_post_flair_widget()
.Add method
add_menu()
.Add method
add_button_widget()
.Add method
reorder()
to reorder a subreddit’s widgets.Add
Redditors
(reddit.redditors
) to provideRedditor
listings.Add
submit_image()
for submitting native images to Reddit.Add
submit_video()
for submitting native videos and videogifs to Reddit.
Changed
SubredditLinkFlairTemplates.__iter__()
uses the v2 flair API endpoint. This change will result in additional fields being returned. All fields that were previously returned will still be returned.SubredditRedditorFlairTemplates.__iter__()
uses the v2 flair API endpoint. The method will still return the exact same items.Methods
SubredditRedditorFlairTemplates.add()
,SubredditLinkFlairTemplates.add()
,SubredditRedditorFlairTemplates.update()
, andSubredditLinkFlairTemplates.update()
can add and update redesign-style flairs with the v2 flair API endpoint. They can still update pre-redesign-style flairs with the older endpoint.
Fixed
Widgets of unknown types are parsed as
Widget
s rather than raising an exception.
6.0.0 (2018/07/24)
Added
Add method
revision()
to get a specific wiki page revision.Added parameter
skip_existing
tostream_generator()
to skip existing items when starting a stream.Add method
Front.best()
to get the front page “best” listing.Add
Subreddit.widgets
,SubredditWidgets
, and widget subclasses likeTextArea
to support fetching Reddit widgets.Add method
Submission.mark_visited()
to mark a submission as visited on the Reddit backend.
Fixed
Fix
RecursionError
onSubredditEmoji
’srepr
andstr
.SubredditFilters.add()
andSubredditFilters.remove()
also accept aSubreddit
for thesubreddit
parameter.Remove restriction which prevents installed (non-confidential) apps from using OAuth2 authorization code grant flow.
Removed
Subreddit.submissions
as the API endpoint backing the method is no more. See https://www.reddit.com/r/changelog/comments/7tus5f/update_to_search_api/.
5.4.0 (2018/03/27)
Added
Add method
patch()
toReddit
class to support HTTP PATCH requests.Add class
Preferences
to access and update Reddit preferences.Add attribute
User.preferences
to access an instance ofPreferences
.Add method
Message.delete()
.Add class
Emoji
to work with custom subreddit emoji.
Deprecated
Subreddit.submissions
as the API endpoint backing the method is going away. See https://www.reddit.com/r/changelog/comments/7tus5f/update_to_search_api/.
Fixed
Fix bug with positive
pause_after
values in streams provided bystream_generator()
where the wait time was not reset after a yieldedNone
.Parse URLs with trailing slashes and no
"comments"
element when creatingSubmission
objects.Fix bug where
Subreddit.submissions
returns a same submission more than onceFix bug where
ListingGenerator
fetches the same batch of submissions in an infinite loop when"before"
parameter is provided.
Removed
Removed support for Python 3.3 as it is no longer supported by requests.
5.3.0 (2017/12/16)
Added
Multireddit.stream
, to stream submissions and comments from a multireddit.
Fixed
Now raises
prawcore.UnavailableForLegalReasons
instead of anAssertionError
when encountering a HTTP 451 response.
5.2.0 (2017/10/24)
Changed
An attribute on
LiveUpdate
now works as lazy attribute (i.e., populate an attribute when the attribute is first accessed).
Deprecated
subreddit.comments.gilded
because there isn’t actually an endpoint that returns only gilded comments. Usesubreddit.gilded
instead.
Fixed
Removed
comment.permalink()
becausecomment.permalink
is now an attribute returned by Reddit.
5.1.0 (2017/08/31)
Added
Redditor.stream
, with methodsRedditorStream.submissions()
andRedditorStream.comments()
to stream a Redditor’s comments or submissionsRedditorStream
has been added to facilitateRedditor.stream
Inbox.collapse()
to mark messages as collapsed.Inbox.uncollapse()
to mark messages as uncollapsed.Raise
ClientException
when callingComment.refresh()
when the comment does not appear in the resulting comment tree.Submission.crosspost()
to crosspost to a subreddit.
Fixed
Calling
Comment.refresh()
on a directly fetched, deeply nestedComment
will additionally pull in as many parent comments as possible (currently 8) enabling significantly quicker traversal to the top-mostComment
via successiveparent()
calls.Calling
refresh()
previously could have resulted in aAttributeError: "MoreComments" object has no attribute "_replies"
exception. This situation will now result in aClientException
.Properly handle
BAD_CSS_NAME
errors when uploading stylesheet images with invalid filenames. Previously anAssertionError
was raised.Submission
’sgilded
attribute properly returns the expected value from reddit.
5.0.1 (2017/07/11)
Fixed
5.0.0 (2017/07/04)
Added
Comment.disable_inbox_replies()
,Comment.enable_inbox_replies()
Submission.disable_inbox_replies()
, andSubmission.enable_inbox_replies()
to toggle inbox replies on comments and submissions.
Changed
cloudsearch
is no longer the default syntax forsearch()
.lucene
is now the default syntax so that PRAW’s default is aligned with Reddit’s default.Reddit.info()
will now take either a list of fullnames or a single URL string.Subreddit.submit()
accepts a flair template ID and text.
Fixed
Fix accessing
LiveUpdate.contrib
raisesAttributeError
.
Removed
Iterating directly over
SubredditRelationship
(e.g.,subreddit.banned
,subreddit.contributor
,subreddit.moderator
, etc) andSubredditFlair
is no longer possible. Iterate instead over their callables, e.g.subreddit.banned()
andsubreddit.flair()
.The following methods are removed:
Subreddit.mod.approve
,Subreddit.mod.distinguish
,Subreddit.mod.ignore_reports
,Subreddit.mod.remove
,Subreddit.mod.undistinguish
,Subreddit.mod.unignore_reports
.Support for passing a
Submission
toSubredditFlair.set()
is removed.The
thing
argument toSubredditFlair.set()
is removed.Return values from
Comment.block()
,Message.block()
,SubredditMessage.block()
,SubredditFlair.delete()
,friend()
,Redditor.message()
,Subreddit.message()
,select()
, andunfriend()
are removed as they do not provide any useful information.praw.ini
no longer reads inhttp_proxy
andhttps_proxy
settings.is_link
parameter ofSubredditRedditorFlairTemplates.add()
andSubredditRedditorFlairTemplates.clear()
. UseSubredditLinkFlairTemplates
instead.
4.6.0 (2017/07/04)
The release’s sole purpose is to announce the deprecation of the is_link
parameter
as described below:
Added
SubredditFlair.link_templates
to manage link flair templates.
Deprecated
is_link
parameter ofSubredditRedditorFlairTemplates.add()
andSubredditRedditorFlairTemplates.clear()
. UseSubredditLinkFlairTemplates
instead.
4.5.1 (2017/05/07)
Fixed
Calling
parent()
works onComment
instances obtained viacomment_replies()
.
4.5.0 (2017/04/29)
Added
Modmail.unread_count()
to get unread count by conversation state.Modmail.bulk_read()
to mark conversations as read by conversation state.Modmail.subreddits()
to fetch subreddits using new modmail.Modmail.create()
to create a new modmail conversation.ModmailConversation.read()
to mark modmail conversations as read.ModmailConversation.unread()
to mark modmail conversations as unread.conversations()
to get new modmail conversations.ModmailConversation.highlight()
to highlight modmail conversations.ModmailConversation.unhighlight()
to unhighlight modmail conversations.ModmailConversation.mute()
to mute modmail conversations.ModmailConversation.unmute()
to unmute modmail conversations.ModmailConversation.archive()
to archive modmail conversations.ModmailConversation.unarchive()
to unarchive modmail conversations.ModmailConversation.reply()
to reply to modmail conversations.Modmail.__call__()
to get a new modmail conversation.Inbox.stream()
to stream new items in the inbox.Exponential request delay to all streams when no new items are returned in a request. The maximum delay between requests is 66 seconds.
Changed
submit()
acceptsselftext=''
to create a title-only submission.Reddit
acceptsrequestor_class=cls
for a customized requestor class andrequestor_kwargs={"param": value}
for passing arguments to requestor initialization.SubredditStream.comments()
,SubredditStream.submissions()
, andSubreddits.stream()
accept apause_after
argument to allow pausing of the stream. The default value ofNone
retains the preexisting behavior.
Deprecated
cloudsearch
will no longer be the default syntax forSubreddit.search()
in PRAW 5. Instead,lucene
will be the default syntax so that PRAW’s default is aligned with Reddit’s default.
Fixed
Fix bug where
WikiPage
revisions with deleted authors causedTypeError
.Submission
attributescomment_limit
andcomment_sort
maintain their values after making instances non-lazy.
4.4.0 (2017/02/21)
Added
LiveThreadContribution.update()
to update settings of a live thread.reset_timestamp
tolimits()
to provide insight into when the current rate limit window will expire.upload_mobile_header()
to upload subreddit mobile header.upload_mobile_icon()
to upload subreddit mobile icon.delete_mobile_header()
to remove subreddit mobile header.delete_mobile_icon()
to remove subreddit mobile icon.LiveUpdateContribution.strike()
to strike a content of a live thread.LiveContributorRelationship.update()
to update contributor permissions for a redditor.LiveContributorRelationship.update_invite()
to update contributor invite permissions for a redditor.LiveThread.discussions()
to get submissions linking to the thread.LiveThread.report()
to report the thread violating the Reddit rules.LiveHelper.now()
to get the currently featured live thread.LiveHelper.info()
to fetch information about each live thread in live thread IDs.
Fixed
Uploading an image resulting in too large of a request (>500 KB) now raises
prawcore.TooLarge
instead of anAssertionError
.Uploading an invalid image raises
APIException
.Redditor
instances obtained viamoderator
(e.g.,reddit.subreddit("test").moderator()
) will contain attributes with the relationship metadata (e.g.,mod_permissions
).Message
instances retrieved from the inbox now have attributesauthor
,dest
replies
andsubreddit
properly converted to their appropriate PRAW model.
4.3.0 (2017/01/19)
Added
LiveContributorRelationship.leave()
to abdicate the live thread contributor position.LiveContributorRelationship.remove()
to remove the redditor from the live thread contributors.limits()
to provide insight into number of requests made and remaining in the current rate limit window.LiveThread.contrib
to obtain an instance ofLiveThreadContribution
.LiveThreadContribution.add()
to add an update to the live thread.LiveThreadContribution.close()
to close the live thread permanently.LiveUpdate.contrib
to obtain an instance ofLiveUpdateContribution
.LiveUpdateContribution.remove()
to remove a live update.LiveContributorRelationship.accept_invite()
to accept an invite to contribute the live thread.SubredditHelper.create()
andSubredditModeration.update()
have documented support forspoilers_enabled
. Note, however, thatSubredditModeration.update()
will currently unset thespoilers_enabled
value until such a time that Reddit returns the value along with the other settings.spoiler()
andunspoiler()
to change a submission’s spoiler status.
Fixed
LiveContributorRelationship.invite()
andLiveContributorRelationship.remove_invite()
now hit endpoints, which starts with “api/”, for consistency.ModeratorRelationship.update()
, andModeratorRelationship.update_invite()
now always remove known unlisted permissions.
4.2.0 (2017/01/07)
Added
.Subreddit.rules
to get the rules of a subreddit.LiveContributorRelationship
, which can be obtained throughLiveThread.contributor
, to interact with live threads’ contributors.remove_invite()
to remove a moderator invite.LiveContributorRelationship.invite()
to send a contributor invitation.LiveContributorRelationship.remove_invite()
to remove the contributor invitation.
Deprecated
Return values from
Comment.block()
,Message.block()
,SubredditMessage.block()
,SubredditFlair.delete()
,friend()
,Redditor.message()
,Subreddit.message()
,select()
, andunfriend()
will be removed in PRAW 5 as they do not provide any useful information.
Fixed
hide()
andunhide()
now accept a list of additional submissions.replace_more()
is now recoverable. Previously, when an exception was raised during the work done byreplace_more()
, all unreplacedMoreComments
instances were lost. NowMoreComments
instances are only removed once their children have been added to theCommentForest
enabling callers ofreplace_more()
to call the method as many times as required to complete the replacement.Working with contributors on
SubredditWiki
is done consistently throughcontributor
notcontributors
.Subreddit.moderator()
works.live_thread.contributor()
now returnsRedditorList
correctly.
Removed
validate_time_filter
is no longer part of the public interface.
4.1.0 (2016/12/24)
Added
Subreddits.search_by_topic()
to search subreddits by topic. (see: https://www.reddit.com/dev/api/#GET_api_subreddits_by_topic).LiveHelper.__call__()
to provide interface topraw.models.LiveThread.__init__
.SubredditFilters
to work with filters for special subreddits, liker/all
.Added callables for
SubredditRelationship
andSubredditFlair
so thatlimit
and other parameters can be passed.Add
Message.reply()
toMessage
which was accidentally missed previously.Add
sticky
parameter toCommentModeration.distinguish()
to sticky comments.Submission.flair()
to add a submission’s flair from an instance ofSubmission
.Comment.parent()
to obtain the parent of aComment
.opt_in()
andopt_out()
toSubreddit
to permit working with quarantined subreddits.LiveUpdate
to represent an individual update in aLiveThread
.Ability to access an individual
LiveUpdate
viareddit.live("THREAD_ID")["UPDATE_ID"]
.LiveThread.updates()
to iterate the updates of the thread.
Changed
me()
now caches its result in order to reduce redundant requests for methods that depend on it. Setuse_cache=False
when calling to bypass the cache.replace_more()
can be called onComment
replies
.
Deprecated
validate_time_filter
will be removed from the public interface in PRAW 4.2 as it was never intended to be part of it to begin with.Iterating directly over
SubredditRelationship
(e.g.,subreddit.banned
,subreddit.contributor
,subreddit.moderator
, etc) andSubredditFlair
will be removed in PRAW 5. Iterate instead over their callables, e.g.subreddit.banned()
andsubreddit.flair()
.The following methods are deprecated to be removed in PRAW 5 and are replaced with similar
Comment.mod...
andSubmission.mod...
alternatives:Subreddit.mod.approve
,Subreddit.mod.distinguish
,Subreddit.mod.ignore_reports
,Subreddit.mod.remove
,Subreddit.mod.undistinguish
,Subreddit.mod.unignore_reports
.Support for passing a
Submission
toSubredditFlair.set()
will be removed in PRAW 5. UseSubmission.flair()
instead.The
thing
argument toSubredditFlair.set()
is replaced withredditor
and will be removed in PRAW 5.
Fixed
SubredditModeration.update()
accurately updatesexclude_banned_modqueue
,header_hover_text
,show_media
andshow_media_preview
values.Instances of
Comment
obtained through the inbox (including mentions) are now refreshable.Searching
r/all
should now work as intended for all users.Accessing an invalid attribute on an instance of
Message
will raiseAttributeError
instead ofPRAWException
.
4.0.0 (2016/11/29)
Fixed
Fix bug where ipython tries to access attribute
_ipython_canary_method_should_not_exist_
resulting in a useless fetch.Fix bug where
Comment
replies becomes[]
after attempting to access an invalid attribute on the Comment.Reddit.wiki[…] converts the passed in page name to lower case as pages are only saved in lower case and non-lower case page names results in a Redirect exception (thanks pcjonathan).
4.0.0rc3 (2016/11/26)
Added
implicit
parameter tourl()
to support the implicit flow for installed applications (see: https://github.com/reddit/reddit/wiki/OAuth2#authorization-implicit-grant-flow)scopes()
to discover which scopes are available to the current authenticationLots of documentation: https://praw.readthedocs.io/
4.0.0rc2 (2016/11/20)
Fixed
Auth.authorize()
properly sets the session’s Authentication (thanks @williammck).
4.0.0rc1 (2016/11/20)
PRAW 4 introduces significant breaking changes. The numerous changes are not listed here, only the feature removals. Please read through Quick Start to help with updating your code to PRAW 4. If you require additional help please ask on r/redditdev or via Slack.
Added
Comment.block()
,Message.block()
, andSubredditMessage.block()
to permit blocking unwanted user contact.LiveHelper.create()
to create new live threads.Redditor.unblock()
to undo a block.Subreddits.gold()
to iterate through gold subreddits.Subreddits.search()
to search for subreddits by name and description.Subreddits.stream()
to obtain newly created subreddits in near realtime.User.karma()
to retrieve the current user’s subreddit karma.praw.models.reddit.submission.SubmissionModeration.lock
andpraw.models.reddit.submission.SubmissionModeration.unlock
to change a Submission’s lock state.SubredditFlairTemplates.delete()
to delete a single flair template.SubredditModeration.unread()
to iterate over unread moderation messages.ModeratorRelationship.invite()
to invite a moderator to a subreddit.ModeratorRelationship.update()
to update a moderator’s permissions.ModeratorRelationship.update_invite()
to update an invited moderator’s permissions.Front.random_rising()
,Subreddit.random_rising()
andMultireddit.random_rising()
.WikiPage
supports a revision argument.SubredditWiki.revisions()
to obtain a list of recent revisions to a subreddit.WikiPage.revisions()
to obtain a list of revisions for a wiki page.Support installed-type OAuth apps.
Support read-only OAuth for all application types.
Support script-type OAuth apps.
Changed
Note
Only prominent changes are listed here.
helpers.comments_stream
is nowSubredditStream.comments()
helpers.submissions_between
is nowSubreddit.submissions
. This new method now only iterates through newest submissions first and as a result makes approximately 33% fewer requests.helpers.submission_stream
is nowSubredditStream.submissions()
Removed
Removed
Reddit
’slogin
method. Authentication must be done through OAuth.Removed
praw-multiprocess
as this functionality is no longer needed with PRAW 4.Removed non-oauth functions
Message.collapse
andMessage.uncollapse
is_username_available
.Removed captcha related functions.
For changes prior to version 4.0 please see: 3.6.2 changelog
Contributing to PRAW
PRAW gladly welcomes new contributions. As with most larger projects, we have an established consistent way of doing things. A consistent style increases readability, decreases bug-potential and makes it faster to understand how everything works together.
Setting Up Your Development Environment
This section will cover the recommended steps to get you started with contributing to PRAW.
Create a Virtual Environment
It is strongly recommended to use a virtual environment to isolate your development environment. This is a good idea because it will make managing the needed dependencies and their versions much easier. For more information, see the venv documentation. Assuming you have the minimum Python version required for PRAW, you can create a virtual environment with the following commands from the root of the cloned project directory:
python3 -m venv .venv
Next you need to activate the virtual environment. This is done by running the following:
MacOS/Linux:
source .venv/bin/activate
Windows Command Prompt
.venv\Scripts\activate.bat
Install Development Dependencies
Next, you will need to install the dependencies development dependencies. This is done by running the following:
pip install -e .[dev]
Important
If you are using zsh
for your shell, you will need to double-quote .[dev]
like so:
pip install -e ".[dev]"
Note
The -e
tells pip to install PRAW in an editable state. This will allow for
easier testing and debugging. The [dev]
extra will install all development
dependencies. This includes the dependencies for both linting and testing.
Code Style
Linting
PRAW follows PEP 8 and PEP 257 and some PRAW Specific Style Guidelines.
pre-commit is used to manage a suite of pre-commit hooks that enforce conformance with
these PEPs along with several other checks. Additionally, the pre_push.py
script can
be used to run the full pre-commit suite and the docs build prior to submitting a pull
request.
Note
In order to use the pre-commit hooks and the pre_push.py
dependencies, you must
either install the development dependencies as outlined in the
Install Development Dependencies section above or you must install the [lint]
extra
manually:
pip install -e .[lint]
To install the pre-commit hooks to automatically run when you commit, run the following:
pre-commit install
To run all the needed checks and to ensure the docs build correctly, run the following:
./pre_push.py
PRAW Specific Style Guidelines
The following are PRAW-specific guidelines in addition to the PEPs specified in Linting:
Within a single file classes are sorted alphabetically where inheritance permits.
Within a class, methods are sorted alphabetically within their respective groups with the following as the grouping order:
Static methods
Class methods
Cached properties
Properties
Instance Methods
Use descriptive names for the catch-all keyword argument, e.g.,
**other_options
rather than**kwargs
.Methods with more than one argument should have all its arguments sorted alphabetically and marked as keyword only with the
*
argument. For example:class ExampleClass: def example_method( self, *, arg1, arg2, optional_arg1=None, ): ...
There is some exceptions to this:
If it’s clear without reading documentation what the mandatory positional arguments would be and their order, then they can be positional arguments. For example:
class ExampleClass: def pair(self, left, right): ...
If there is one or two mandatory arguments and some optional arguments, then the mandatory arguments may be positional (as long as it adheres to the previous point), however, the optional arguments must be made keyword only and sorted alphabetically. For example:
class Subreddit: def submit( self, title, *, collection_id=None, discussion_type=None, draft_id=None, flair_id=None, flair_text=None, inline_media=None, nsfw=False, resubmit=True, selftext=None, send_replies=True, spoiler=False, url=None, ): ...
Testing
Contributions to PRAW requires 100% test coverage as reported by Coveralls. If you know how to add a feature, but aren’t sure how to write the necessary tests, please open a pull request anyway so we can work with you to write the necessary tests.
Running the Test Suite
GitHub Actions automatically runs all updates to known branches and pull requests. However, it’s useful to be able to run the tests locally. The simplest way is via:
pytest
Without any configuration or modification, all the tests should pass. If they do not, please file a bug report.
Adding and Updating Integration Tests
PRAW’s integration tests utilize Betamax to record an interaction with Reddit. The recorded interaction is then replayed for subsequent test runs.
To safely record a cassette without leaking your account credentials, PRAW utilizes a number of environment variables which are replaced with placeholders in the cassettes. The environment variables are (listed in bash export format):
export prawtest_client_id=myclientid
export prawtest_client_secret=myclientsecret
export prawtest_password=mypassword
export prawtest_test_subreddit=test
export prawtest_username=myusername
export prawtest_user_agent=praw_pytest
By setting these environment variables prior to running pytest
, when adding or
updating cassettes, instances of mypassword
will be replaced by the placeholder text
<PASSWORD>
and similar for the other environment variables.
To use a refresh token instead of username/password set prawtest_refresh_token
instead of prawtest_password
and prawtest_username
.
When adding or updating a cassette, you will likely want to force requests to occur again rather than using an existing cassette. The simplest way to rebuild a cassette is to first delete it, and then rerun the test suite.
Please always verify that only the requests you expect to be made are contained within your cassette.
There are a few pytest markers that can be used to control how cassettes are recorded or used.
@pytest.mark.add_placeholder
: Allows you to add custom placeholders to the cassette. This can be useful when you want to record dynamic or generated data, but do not want it to be saved in the cassette. This marker takes at least one keyword argument and can be applied to a test class or individual test methods. It can also be applied multiple times.@pytest.mark.cassette_name
: Allows you to set the cassette name. This can be useful when you want to use a cassette that was recorded by another test.@pytest.mark.recorder_kwargs
: Allows you to pass additional arguments to the recorder. This can be useful if you need to specify parameters for theBetamax.use_cassette
method. Like theadd_placeholder
marker, this marker can be applied to a test class or individual test methods and can be applied multiple times.
Examples:
@pytest.mark.recorder_kwargs(allow_playback_repeats=True)
class TestClass:
@pytest.mark.recorder_kwargs(match_requests_on=["uri", "method", "body"])
def test_example(self):
...
@pytest.mark.cassette_name("TestClass.test_example")
@pytest.mark.recorder_kwargs(match_requests_on=["uri", "method", "body"])
def test_example__different_assertion(self):
...
@pytest.mark.add_placeholder(generated_data_a=generate_data_a())
@pytest.mark.add_placeholder(generated_data_b=generate_data_b())
def test_example__with_generated_placeholders(self):
...
Documentation
All publicly available functions, classes, and modules should have a docstring.
All documentation files and docstrings should be linted and formatted by
docstrfmt
.Use correct terminology. A subreddit’s fullname is something like
t5_xyfc7
. The correct term for a subreddit’s “name” likepython
for r/python is its display name.
Static Checker
PRAW’s test suite comes with a checker tool that can warn you of using incorrect
documentation styles (using .. code::
instead of .. code-block::
, using /r/
instead of r/
, etc.). This is run automatically by the pre-commit hooks and the
pre_push.py
script.
- class tools.static_word_checks.StaticChecker(replace: bool)
Run simple checks on the entire document or specific lines.
- __init__(replace: bool)
Initialize a
StaticChecker
instance.- Parameters:
replace – Whether or not to make replacements.
- check_for_double_syntax(filename: str, content: str) bool
Checks a file for double-slash statements (
/r/
and/u/
).- Parameters:
filename – The name of the file to check & replace.
content – The content of the file.
- Returns:
A boolean with the status of the check.
- check_for_noreturn(filename: str, line_number: int, content: str) bool
Checks a line for
NoReturn
statements.- Parameters:
filename – The name of the file to check & replace.
line_number – The line number.
content – The content of the line.
- Returns:
A boolean with the status of the check.
- run_checks() bool
Scan a directory and run the checks.
The directory is assumed to be the praw directory located in the parent directory of the file, so if this file exists in
~/praw/tools/static_word_checks.py
, it will check~/praw/praw
.It runs the checks located in the
self.full_file_checks
andself.line_checks
lists, with full file checks being run first.Full-file checks are checks that can also fix the errors they find, while the line checks can just warn about found errors.
Full file checks:
Line checks:
Files to Update
CHANGES.rst
For feature additions, bug fixes, or code removal please add an appropriate entry to
CHANGES.rst
. If the Unreleased
section does not exist at the top of
CHANGES.rst
please add it. See commit 280525c16ba28cdd69cdbb272a0e2764b1c7e6a0
for an example.
See Also
Please also read the Contributing Guidelines
Glossary
Access Token
: A temporary token to allow access to the Reddit API. Lasts for one hour.
Creddit
: Back when the only award wasReddit Gold
, a creddit was equal to one month of Reddit Gold. Creddits have been converted toReddit Coins
. See this for more info about the old Reddit Gold system.
Fullname
: The fullname of an object is the object’s type followed by an underscore and its base-36 id. An example would bet3_1h4f3
, where thet3
signals that it is aSubmission
, and the submission ID is1h4f3
.Here is a list of the six different types of objects returned from Reddit:
t1
These object representComment
s.
t2
These object representRedditor
s.
t3
These object representSubmission
s.
t4
These object representMessage
s.
t5
These object representSubreddit
s.
t6
These object representAward
s, such asReddit Gold
orReddit Silver
.
Gild
: Back when the only award wasReddit Gold
, gilding a post meant awarding one month of Reddit Gold. Currently, gilding means awarding one month ofReddit Platinum
, or giving aPlatinum
award.
Websocket
: A special connection type that supports both a client and a server (the running program and Reddit respectively) sending multiple messages to each other. Reddit uses websockets to notify clients when an image or video submission is completed, as well as certain types of asset uploads, such as subreddit banners.
Migrating to PRAW 7.X
Exception Handling
Class APIException
has also been renamed to RedditAPIException
.
Importing APIException
will still work, but is deprecated, but will be removed
in PRAW 8.0.
PRAW 7 introduced a fundamental change in how exceptions are received from Reddit’s API.
Reddit can return multiple exceptions for one API action, and as such, the exception
RedditAPIException
serves as a container for each of the true exception
objects. These objects are instances of RedditErrorItem
, and they contain the
information of one “error” from Reddit’s API. They have the three data attributes that
APIException
used to contain.
Most code regarding exceptions can be quickly fixed to work under the new system. All of
the exceptions are stored in the items
attribute of the exception as entries in a
list. In the example code below, observe how attributes are accessed.
try:
reddit.subreddit("test").submit("Test Title", url="invalidurl")
except APIException as exception:
print(exception.error_type)
This can generally be changed to:
try:
reddit.subreddit("test").submit("Test Title", url="invalidurl")
except RedditAPIException as exception:
print(exception.items[0].error_type)
However, this should not be done, as this will only work for one error. The probability of Reddit’s API returning multiple exceptions, especially on submit actions, should be addressed. Rather, iterate over the exception, and do the action on each item in the iterator.
try:
reddit.subreddit("test").submit("Test Title", url="invalidurl")
except RedditAPIException as exception:
for subexception in exception.items:
print(subexception.error_type)
Alternatively, the exceptions are provided to the exception constructor, so printing the exception directly will also allow you to see all the exceptions.
try:
reddit.subreddit("test").submit("Test Title", url="invalidurl")
except RedditAPIException as exception:
print(exception)
References
Reddit Source Code. This repository has been archived and is no longer updated.
Reddit Help. Frequently asked questions and a knowledge base for the site.
Reddit Markdown Primer. A guide to the Markdown formatting used on the site.
Reddit Status. Indicates when Reddit is up or down.
r/changelog. Significant changes to Reddit’s codebase will be announced here in non-developer speak.
r/redditdev. Ask questions about Reddit’s codebase, PRAW, and other API clients here.
Sponsors

Comment Extraction and Parsing
A common use for Reddit’s API is to extract comments from submissions and use them to perform keyword or phrase analysis.
As always, you need to begin by creating an instance of
Reddit
:Note
If you are only analyzing public comments, entering a username and password is optional.
In this document, we will detail the process of finding all the comments for a given submission. If you instead want to process all comments on Reddit, or comments belonging to one or more specific subreddits, please see
SubredditStream.comments()
.Extracting comments with PRAW
Assume we want to process the comments for this submission: https://www.reddit.com/r/funny/comments/3g1jfi/buttons/
We first need to obtain a submission object. We can do that either with the entire URL:
or with the submission’s ID which comes after
comments/
in the URL:With a submission object we can then interact with its
CommentForest
through the submission’sSubmission.comments
attribute. ACommentForest
is a list of top-level comments each of which contains aCommentForest
of replies.If we wanted to output only the
body
of the top-level comments in the thread we could do:While running this you will most likely encounter the exception
AttributeError: 'MoreComments' object has no attribute 'body'
. This submission’s comment forest contains a number ofMoreComments
objects. These objects represent the “load more comments”, and “continue this thread” links encountered on the website. While we could ignoreMoreComments
in our code, like so:The
replace_more
methodIn the previous snippet, we used
isinstance()
to check whether the item in the comment list was aMoreComments
so that we could ignore it. But there is a better way: theCommentForest
object has a method calledreplace_more()
, which replaces or removesMoreComments
objects from the forest.Each replacement requires one network request, and its response may yield additional
MoreComments
instances. As a result, by default,replace_more()
only replaces at most 32MoreComments
instances – all other instances are simply removed. The maximum number of instances to replace can be configured via thelimit
parameter. Additionally athreshold
parameter can be set to only perform replacement ofMoreComments
instances that represent a minimum number of comments; it defaults to0
, meaning allMoreComments
instances will be replaced up tolimit
.A
limit
of0
simply removes allMoreComments
from the forest. The previous snippet can thus be simplified:Note
Calling
replace_more()
is destructive. Calling it again on the same submission instance has no effect.Meanwhile, a
limit
ofNone
means that allMoreComments
objects will be replaced until there are none left, as long as they satisfy thethreshold
.Now we are able to successfully iterate over all the top-level comments. What about their replies? We could output all second-level comments like so:
However, the comment forest can be arbitrarily deep, so we’ll want a more robust solution. One way to iterate over a tree, or forest, is via a breadth-first traversal using a queue:
The above code will output all the top-level comments, followed by second-level, third-level, etc. While it is awesome to be able to do your own breadth-first traversals,
CommentForest
provides a convenience method,list()
, which returns a list of comments traversed in the same order as the code above. Thus the above can be rewritten as:You can now properly extract and parse all (or most) of the comments belonging to a single submission. Combine this with submission iteration and you can build some really cool stuff.
Finally, note that the value of
submission.num_comments
may not match up 100% with the number of comments extracted via PRAW. This discrepancy is normal as that count includes deleted, removed, and spam comments.