Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

snoowrap

not-an-aardvark37.9kMIT1.23.0TypeScript support: included

A JavaScript wrapper for the reddit API

reddit, api, wrapper, praw, snoo

readme

snoowrap Build Status Gitter chat

A fully-featured JavaScript wrapper for the reddit API. (Documentation)

Features

  • snoowrap provides a simple interface to access every reddit API endpoint. For example, the method to get a user profile is just getUser(), and the method to upvote something is just upvote().
  • snoowrap is non-blocking; all of its API calls are asynchronous and return bluebird Promises. This means that you can handle concurrent requests however you want to, and you can use snoowrap as part of a larger process without it holding everything back.
  • Each snoowrap object is completely independent. This means that you can have scripts from separate accounts making requests at the same time.
  • After you provide a token once, snoowrap will refresh it on its own from then on -- you won't have to worry about authentication again.
  • snoowrap uses lazy objects, so it never fetches more than it needs to.
  • snoowrap has built-in ratelimit protection. If you hit reddit's ratelimit, you can choose to queue the request, and then run it after the current ratelimit period runs out. That way you won't lose a request if you go a bit too fast.
  • snoowrap will retry its request a few times if reddit returns an error due to its servers being overloaded.

These features ensure that you can write less boilerplate code and focus more on actually doing what you want to do.


snoowrap's methods are designed to be as simple and consistent as possible. So the following expression:

r.getSubmission('2np694').body

...will return a Promise. So will this one:

 r.getSubmission('2np694').author.name
 // --> returns a Promise for the string 'DO_U_EVN_SPAGHETTI'
 // (this submission's author's name)

The above will return a Promise for the author's name, without having to deal with callback hell or .then statements. You can chain multiple API calls together:

r.getSubmission('2np694').subreddit.getModerators()[0].name
// --> returns a Promise for the string 'krispykrackers'
// (this submission's subreddit's first mod's name)

...or chain actions together with fluent syntax:

r.getSubreddit('snoowrap')
  .submitSelfpost({title: 'Discussion Thread', text: 'Hello! This is a thread'})
  .sticky()
  .distinguish()
  .ignoreReports()
  .assignFlair({text: 'Exciting Flair Text', css_class: 'modpost'})

snoowrap works on Node.js 4+, as well as most common browsers.


Examples

'use strict';
const snoowrap = require('snoowrap');

// NOTE: The following examples illustrate how to use snoowrap. However, hardcoding
// credentials directly into your source code is generally a bad idea in practice (especially
// if you're also making your source code public). Instead, it's better to either (a) use a separate
// config file that isn't committed into version control, or (b) use environment variables.

// Create a new snoowrap requester with OAuth credentials.
// For more information on getting credentials, see here: https://github.com/not-an-aardvark/reddit-oauth-helper
const r = new snoowrap({
  userAgent: 'put your user-agent string here',
  clientId: 'put your client id here',
  clientSecret: 'put your client secret here',
  refreshToken: 'put your refresh token here'
});

// Alternatively, just pass in a username and password for script-type apps.
const otherRequester = new snoowrap({
  userAgent: 'put your user-agent string here',
  clientId: 'put your client id here',
  clientSecret: 'put your client secret here',
  username: 'put your username here',
  password: 'put your password here'
});

// That's the entire setup process, now you can just make requests.

// Submitting a link to a subreddit
r.getSubreddit('gifs').submitLink({
  title: 'Mt. Cameramanjaro',
  url: 'https://i.imgur.com/n5iOc72.gifv'
});

// Printing a list of the titles on the front page
r.getHot().map(post => post.title).then(console.log);

// Extracting every comment on a thread
r.getSubmission('4j8p6d').expandReplies({limit: Infinity, depth: Infinity}).then(console.log)

// Automating moderation tasks
r.getSubreddit('some_subreddit_name').getModqueue({limit: 100}).filter(someRemovalCondition).forEach(flaggedItem => {
  flaggedItem.remove();
  flaggedItem.subreddit.banUser(flaggedItem.author);
});

// Automatically creating a stickied thread for a moderated subreddit
r.getSubreddit('some_subreddit_name')
  .submitSelfpost({title: 'Daily thread', text: 'Discuss things here'})
  .sticky()
  .distinguish()
  .approve()
  .assignFlair({text: 'Daily Thread flair text', css_class: 'daily-thread'})
  .reply('This is a comment that appears on that daily thread');
  // etc. etc.

// Printing the content of a wiki page
r.getSubreddit('AskReddit').getWikiPage('bestof').content_md.then(console.log);

For more examples of what can be done with snoowrap, take a look at the documentation.


Live threads

Reddit's live threads are different from most other content, in that messages are distributed through websockets instead of a RESTful API. snoowrap supports this protocol under the hood by representing the content stream as an EventEmitter. For example, the following script will stream all livethread updates to the console as they appear:

r.getLivethread('whrdxo8dg9n0').stream.on('update', console.log);

For more information, see the LiveThread documentation page.


Important note on ES6

snoowrap uses the Proxy object introduced in ES6.

If your target environment does not support Proxies, snoowrap will still function. However, method chaining as described above won't work, so your syntax will need to be a bit heavier.

Environments that support the ES6 Proxy object

  • Node 6+
  • Chrome 49+
  • Firefox 18+
  • Edge
  • Node 4 and 5 (requires the --harmony_proxies runtime flag to be enabled. e.g. node --harmony_proxies yourFile.js)

Example of how Proxy support affects behavior:

// This works in environments that support Proxies.
// However, it throws a TypeError if Proxies are not available.
r.getSubmission('47v7tm').comments[0].upvote();

// ----------

// This is equivalent and works on all platforms, but the syntax isn't as nice.
r.getSubmission('47v7tm').fetch().then(submission => {
  return submission.comments[0].upvote();
});

You can explicitly disable method chaining with r.config({proxies: false}).


To include in a project

Node:

npm install snoowrap --save
var snoowrap = require('snoowrap');

Browsers:

snoowrap is usable with module bundlers such as browserify.

Alternatively, prebuilt versions are available:

These files will occasionally be updated as new versions of snoowrap 1 are released. Since snoowrap follows semantic versioning, the changes should not break your code. However, if you would prefer to pin the version, you can specify a version number in the URL (e.g. snoowrap-v1.11.3.min.js). For a list of all available prebuilt versions, see the gh-pages branch of this repository.

When run in a browser, snoowrap will be assigned to the global variable window.snoowrap. If you want to avoid global state (or you're using two versions of snoowrap on the same page for some reason), use snoowrap.noConflict() to restore window.snoowrap to its previous value.

To build/run the tests independently

See the contributing guide and the getting started page.


License

This software is freely distributable under the MIT License.

changelog

Changelog

v1.22.0

  • Added catch-all options for Subreddit#editSettings
  • TS: added appeals value to new modmail count
  • TS: fixed typo in Subreddit#submitSelfpost
  • TS: added type definition for snoowrap#getContentByIds
  • TS: more properties to SubmitLinkOptions interface
  • TS: more properties to SearchOptions interface
  • TS: added removed_by_category property to Submission
  • TS: fixed snoowrap#getPopularSubreddits typo
  • Fix missing commas in JSDoc examples
  • Fix window.location usage in JSDoc
  • Test: fixed failing test suite

v1.21.0 (2020-02-24)

  • Added permanent option to snoowrap#applicationOnlyAuth
  • Added ModmailConversation#reply()
  • TS: Added snoowrap#getBest() definitions
  • Bump dependencies

v1.20.1 (2019-11-14)

  • Updated snoowrap#applicationOnlyAuth TypeScript definitions
  • Fixed TypeScript definitions for TypeScript v3.7.0
  • Fixed incorrect check for deviceId in snoowrap#applicationOnlyAuth
  • Fix incorrect docs for DO_NOT_TRACK_THIS_DEVICE param in snoowrap#applicationOnlyAuth

v1.20.0 (2019-10-07)

  • Added application only auth snoowrap#applicationOnlyAuth
  • Fixed ModmailConversation TypeScript definitions
  • Converted ModmailConversationAuthor to TypeScript

v1.19.0 (2019-08-05)

  • Added TypeScript definitions
  • Added Subreddit#getNewModmailConversations
  • Added snoowrap#getContentByIds

v1.18.0 (2019-07-23)

  • Added support for locking and unlocking comments

v1.17.0 (2019-06-13)

  • Deprecated MultiReddit#rename (this endpoint is no longer supported by reddit.com)

v1.16.0 (2019-06-04)

  • Added support for new modmail
  • Added /best endpoint

v1.15.2 (2018-01-05)

  • Fixed an error when deleting images from subreddit stylesheets
  • Fixed an issue where snoowrap would fail to change the visibility of a subreddit

v1.15.1 (2017-11-27)

  • Re-release after accidentally publishing a broken package to npm

v1.15.0 (2017-11-27)

  • Added snoowrap#submitCrosspost, Submission#submitCrosspost, and Subreddit#submitCrosspost

v1.14.2 (2017-08-09)

  • Added an exponential backoff for failed requests

v1.14.1 (2017-07-07)

  • Fixed an issue where Submission#getDuplicates would return a 404 error
  • Fixed an issue where using an invalid auth code in snoowrap.fromAuthCode would result in a confusing error message

v1.14.0 (2017-05-11)

  • Added support for allow_images and show_media_preview subreddit settings

v1.13.0 (2017-03-30)

  • Added support for marking and unmarking posts as spoilers
  • Fixed an issue where comments on some listings did not have a replies property
  • Fixed an issue where using invalid credentials could result in a confusing error message from snoowrap

v1.12.0 (2017-01-01)

  • Added snoowrap#getRising and subreddit#getRising to get a list of "rising" posts on reddit
  • Fixed an issue where Webpack would throw "missing dependency" errors when including snoowrap

v1.11.3 (2016-11-16)

  • Fixed an issue where Listing#fetchMore returned incorrect results when fetching very large Listings with the append option

v1.11.2 (2016-11-15)

  • Fixed an issue where snoowrap threw an error when fetching PrivateMessages with no replies.
  • Fixed an issue where ratelimit errors caused a confusing error message.
  • Fixed an issue where Promises returned by snoowrap#checkCaptchaRequirement sometimes fulfilled with something other than a boolean.

v1.11.1 (2016-10-27)

  • Fixed a regression where snoowrap#oauthRequest only accepted a uri option and did not accept a url option.

v1.11.0 (2016-10-27)

  • Added snoowrap#getStickiedLivethread, which gets the globally-stickied live-thread if one exists.
  • Added snoowrap#rawRequest, which exposes raw request functionality. This is useful for snoowrap subclasses that want to use custom request logic.

v1.10.0 (2016-10-02)

  • Added snoowrap.getAuthUrl and snoowrap.fromAuthCode functions, to allow for easier authorization of arbitrary accounts in browsers.

v1.9.0 (2016-09-24)

  • Added PrivateMessage#deleteFromInbox, which deletes a private message from the user's inbox.

v1.8.1 (2016-09-08)

  • Fixed an issue where snoowrap#credentialedClientRequest didn't accept this-bindings with snake_case key names.

v1.8.0 (2016-09-08)

  • All of snoowrap's methods and parameters are now in camelCase, to be more aligned with idiomatic JS. This is not a breaking change; for backwards compatibility, snake_case aliases are provided for all methods and parameters. Existing code should still work and does not need to be migrated.
  • Added a snoowrap.noConflict method to avoid relying on global state in browsers

v1.7.1 (2016-09-03)

  • Fixed an issue where Listings sometimes threw errors in Safari

v1.7.0 (2016-08-31)

  • Added a proxies config option to explicitly disable method chaining even if the runtime environment supports the Proxy object

v1.6.2 (2016-08-28)

  • Fixed an issue where credentialed_client_request could not be used in browsers without creating a snoowrap instance

v1.6.1 (2016-08-26)

  • Fixed an issue where snoowrap's package.json file would cause errors when bundling with webpack

v1.6.0 (2016-08-18)

  • Reduced the size of the browser bundle by 77%
  • Fixed an issue where snoowrap did not work on iOS Safari
  • Fixed an issue where an error could get thrown while fetching comment Listings in newer browsers
  • Changed the name of the prebuild browser files to include the snoowrap version, e.g. snoowrap-v1.6.0.min.js. Please use these files rather than the default snoowrap.min.js file from now on.

v1.5.0 (2016-08-06)

  • Added a Subreddit#get_modmail function to get modmail for a specific subreddit
  • snoowrap now requests gzipped content for all requests, which should reduce the amount of bandwidth it uses (#35).
  • Fixed an issue where RedditUser#get_saved would return hidden content instead of saved content (#36)

v1.4.2 (2016-07-30)

  • Fixed an issue where configurations were shared between snoowrap instances instead of being independent
  • Fixed an issue where non-idempotent API requests would be retried after 503 errors, which would occasionally lead to duplicate results. To fix this, only idempotent requests (GET, PUT, and DELETE) are retried.

v1.4.1 (2016-07-04)

  • Fixed an issue where Subreddit#edit_settings sometimes threw errors

v1.4.0 (2016-07-01)

  • Added an append option to the Listing#fetch_more functions indicating whether fetched items should be returned with the existing Listing elements, or returned separately.
  • Fixed an issue where snoowrap wasn't working on OSX Safari

v1.3.0 (2016-06-22)

  • Added support for username/password authentication by passing username and password into the snoowrap constructor

v1.2.0 (2016-06-07)

  • Added camelCase aliases for all exposed snoowrap functions
  • Added support for passing comment IDs to snoowrap#mark_messages_as_read and snoowrap#mark_messages_as_unread
  • Added filtering options for snoowrap#get_inbox

v1.1.1 (2016-05-15)

  • Fixed an issue where a setting a high request_delay would delay script termination
  • Fixed an issue where LiveThread#revoke_contributor_invite would throw errors if Proxies were disabled
  • Fixed an issue where Subreddit#set_multiple_user_flairs could incorrectly report success if an error occurred
  • Fixed an issue where Subreddit#set_multiple_user_flairs would fail if a flair text contained special characters

v1.1.0 (2016-05-13)

  • Added snoowrap#mark_messages_as_read and snoowrap#mark_messages_as_unread functions for dealing with multiple private messages simultaneously
  • Fixed an issue where snoowrap#credentialed_client_request would incorrectly fail when given certain this-bindings

v1.0.0 (2016-05-10)

  • Added a request_timeout config option

If you're upgrading from v0.11.x, note the two small breaking changes introduced in v1.0.0-rc.1.

v1.0.0-rc.2 (2016-05-08)

  • Fixed an issue where snoowrap would crash if it received a 401 error from the reddit API
  • Fixed an issue where 5xx errors from the reddit API were parsed incorrectly
  • Fixed an issue where some methods on snoowrap.prototype were enumerable

v1.0.0-rc.1 (2016-05-07)

  • [breaking]: Removed the suppress_warnings config option in favor of a new warnings option.
  • [breaking]: Subreddit#get_user_flair_list now returns a Promise for a Listing instead of a plain Array, which can be extended as usual. The user property of each item in this Listing is now a RedditUser object rather than a string.
  • Added more lenient input parsing for snoowrap#get_user, snoowrap#get_subreddit, etc.
  • Fixed issues where snoowrap#search_subreddit_names, Subreddit#get_settings, and Subreddit#get_submit_text would fail if Proxies were disabled
  • Fixed an issue where requests immediately following a ratelimit warning at the end of a ratelimit period would not be throttled correctly
  • Fixed an issue where Listing#fetch_all() would consume more requests than necessary
  • Fixed an issue where an unsuccessful image upload could incorrectly report success
  • Fixed an issue where the restrict_sr option on snoowrap#search was always set to true

v0.11.6 (2016-04-27)

  • Exposed oauth_request, credentialed_client_request, unauthenticated_request, and update_access_token functions for sending raw requests to servers
  • Fixed an issue where a TypeError would be thrown if the ratelimit was exceeded and r.config().continue_after_ratelimit_error was set to true (#19)
  • Fixed an issue where Submissions fetched from the front page were missing a .comments property

v0.11.5 (2016-04-23)

  • Fixed an issue where Listing#fetch_all() would sometimes return an incomplete Listing when fetching Comment replies
  • Fixed an issue where the snoowrap constructor was not allowing the client_secret parameter to be an empty string
  • Fixed an issue where RedditContent objects were being converted to JSON incorrectly

v0.11.4 (2016-04-22)

  • Fixed an issue where small comment reply chains were never considered 'finished'

v0.11.3 (2016-04-22)

  • Fixed an issue where Submissions and Comments with a large number of top-level replies could end up with internally-used 'MoreComments' objects in the replies Listing.

v0.11.2 (2016-04-22)

This update contains a few new features and bugfixes.

  • Added a VoteableContent#expand_replies function, which makes it easier to fetch and enumerate large comment trees
  • Added support for fetching deep comment chains in which a "Continue this thread" link appears on the main site
  • Improved the documentation pages:
    • Almost all functions now have usage examples
    • A snoowrap global is exposed for use in the dev console
  • Improved the validation for snoowrap#config parameters
  • Added the ability to block the author of any ReplyableContent object
  • Fixed an issue where unsubscribing from a Subreddit would return a 404 error if the user wasn't subscribed in the first place
  • Fixed an issue where Submission#get_link_flair_templates would throw errors if Proxies were disabled
  • Fixed an issue where LiveThread#get_contributors would have an inconsistent structure if there were any pending contributor invitations
  • Fixed an issue where Subreddit#assign_flair was not returning a chained Promise

v0.11.1 (2016-04-06)

  • Fixed an issue where certain Subreddit functions would throw errors if Proxies were disabled

v0.11.0 (2016-04-05)

This update contains a small number of breaking changes.

  • [breaking] Listings are now immutable. This avoids race conditions that could previously occur while expanding Listings. Listing.prototype.fetch_more now returns a new Listing containing all fetched items, instead of mutating the original Listing.
  • [breaking] PrivateMessage replies are now arranged recursively into a tree structure.
  • Added support for reverse Listing pagination if the before query parameter is set.
  • Added the debug config option, which logs API calls and ratelimit statistics.
  • Added a skip_replies option to Listing.prototype.fetch_more, for faster comment fetching when comment replies are not needed.
  • Added support for Listings to have extended limit properties when being initially fetched. For example, r.get_hot({limit: 150}) will now return a Listing with 150 elements, rather than being capped at 100.

This changelog does not cover versions before v0.11.0.