Documentation
¶
Overview ¶
Package reddit is a dependency-free (stdlib-only, CGO=0) client for Reddit's public read-only JSON API.
It targets the anonymous endpoints that back every subreddit and post page — appending ".json" to any Reddit URL returns the same listing the site renders. No OAuth, no API key: the only requirement Reddit enforces on anonymous traffic is a descriptive, non-generic User-Agent (a missing or browser-mimicking UA earns a 429). Set one with WithUserAgent.
The client is deliberately small and allocation-light so it can be reused unchanged from a native binary, a wasm proxy, or a Ruby binding (github.com/go-ruby-reddit). It builds for every Go target, cgo disabled.
Index ¶
- Constants
- type APIError
- type Client
- func (c *Client) Comments(ctx context.Context, subreddit, id string, opts ListingOptions) (*PostWithComments, error)
- func (c *Client) Frontpage(ctx context.Context, sort Sort, opts ListingOptions) (*Page, error)
- func (c *Client) SearchSubreddits(ctx context.Context, query string, opts ListingOptions) (*SubredditPage, error)
- func (c *Client) Subreddit(ctx context.Context, name string, sort Sort, opts ListingOptions) (*Page, error)
- type Comment
- type ListingOptions
- type Option
- type Page
- type Post
- type PostWithComments
- type Sort
- type SubredditInfo
- type SubredditPage
- type TimeRange
Constants ¶
const DefaultBaseURL = "https://www.reddit.com"
DefaultBaseURL is Reddit's canonical JSON host. The "www" host (rather than "old" or "api") returns the modern listing schema this package decodes.
const DefaultUserAgent = "go-reddit/reddit (+https://github.com/go-reddit/reddit)"
DefaultUserAgent identifies this library. Reddit rate-limits anonymous requests that omit a UA or impersonate a browser, so callers are strongly encouraged to override this with WithUserAgent using their own contact string (Reddit's guidance: "<platform>:<app-id>:<version> (by /u/<name>)").
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type APIError ¶
APIError is returned when Reddit responds with a non-2xx status. It carries the HTTP status code and a short snippet of the body for diagnosis (Reddit serves an HTML or JSON error page on 403/429/5xx).
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client fetches listings and comments from Reddit's public JSON API. The zero value is not usable; construct one with NewClient. A Client is safe for concurrent use as long as the underlying http.Client is.
func NewClient ¶
NewClient returns a Client with sensible defaults (a 30-second HTTP timeout, the canonical base URL, and DefaultUserAgent), then applies each Option in order.
func (*Client) Comments ¶
func (c *Client) Comments(ctx context.Context, subreddit, id string, opts ListingOptions) (*PostWithComments, error)
Comments fetches a post and its comment tree. The comments endpoint returns a two-element array: [ Listing(the post), Listing(the comments) ]. subreddit may be blank (Reddit resolves the post by id alone) but supplying it avoids a redirect. id is the base-36 post id ("abc123"), with or without the "t3_" prefix.
func (*Client) Frontpage ¶
Frontpage fetches the logged-out front page under the given sort (blank defaults to SortHot). This is r/all-ish aggregate content, not a personalised feed (anonymous access has no account).
func (*Client) SearchSubreddits ¶ added in v0.3.0
func (c *Client) SearchSubreddits(ctx context.Context, query string, opts ListingOptions) (*SubredditPage, error)
SearchSubreddits searches Reddit for subreddits whose name, title or description matches query, returning a page of results. Subreddit names cannot be enumerated, so this search endpoint is how a UI discovers them; a caller can further filter the returned names/descriptions locally (e.g. by a regular expression). A blank query is rejected. ListingOptions.Limit (Reddit clamps to 100) and After paginate. Works anonymously or with a configured session cookie / OAuth.
func (*Client) Subreddit ¶
func (c *Client) Subreddit(ctx context.Context, name string, sort Sort, opts ListingOptions) (*Page, error)
Subreddit fetches a page of posts from r/<name> under the given sort. A blank sort defaults to SortHot; a blank name is rejected. The special name "all" and "popular" resolve to Reddit's aggregate feeds.
type Comment ¶
type Comment struct {
ID string `json:"id"`
Fullname string `json:"name"`
Author string `json:"author"`
Body string `json:"body"`
Score int `json:"score"`
CreatedUTC float64 `json:"created_utc"`
Stickied bool `json:"stickied"`
Replies []Comment `json:"-"`
}
Comment is a single "t1" thing in a comment tree. Replies is populated recursively; leaf comments (or the truncated "load more" frontier) have a nil slice.
type ListingOptions ¶
type ListingOptions struct {
// Limit caps the number of posts returned (Reddit clamps to 100).
Limit int
// After is the fullname ("t3_xxxxxx") to page from; use [Page.After].
After string
// Time scopes SortTop / SortControvers; ignored otherwise.
Time TimeRange
}
ListingOptions tunes a listing request. The zero value asks Reddit for its default page size starting at the top of the listing.
type Option ¶
type Option func(*Client)
Option customises a Client at construction time.
func WithBaseURL ¶
WithBaseURL overrides the API host. Primarily a test seam (point it at an httptest server); an empty string is ignored. Any trailing slash is trimmed so path joining stays predictable.
func WithHTTPClient ¶
WithHTTPClient supplies the http.Client used for every request. Use it to inject timeouts, proxies, or a test transport. A nil client is ignored.
func WithOAuth ¶
WithOAuth configures application-only ("client_credentials") OAuth using a registered script/web app's client id and secret. This grants read access to public listings without a user account and works from IPs where the anonymous ".json" endpoints are blocked. Empty credentials are ignored (the Client stays anonymous).
func WithOAuthScript ¶
WithOAuthScript configures the resource-owner-password ("script app") grant, authenticating as a specific Reddit user. Use it when you need per-user context; otherwise prefer WithOAuth. Empty credentials are ignored.
func WithSessionCookie ¶ added in v0.2.0
WithSessionCookie authenticates reads with a logged-in browser's reddit_session cookie instead of OAuth. Reddit's self-serve OAuth registration is effectively closed to new personal projects, so supplying the cookie from an already-signed-in browser is the practical path for individual, read-only use.
The argument may be either the bare reddit_session value or a full "reddit_session=…; other=…" Cookie header string; both normalise to a Cookie header value (a bare value is wrapped as "reddit_session=<value>"; a string that already contains "name=value" pairs is used verbatim). Surrounding whitespace is trimmed and an empty (or whitespace-only) argument is ignored.
Unlike WithOAuth, this keeps the default www base URL — the cookie authenticates the same anonymous ".json" endpoints. When both a session cookie and OAuth are configured, the session cookie takes precedence: the request carries the Cookie header and no Bearer token.
func WithUserAgent ¶
WithUserAgent sets the User-Agent header. An empty string is ignored so the DefaultUserAgent always remains in effect. Reddit blocks generic agents, so production callers should pass a unique, descriptive value.
type Page ¶
Page is a decoded listing: the posts plus the paging cursors Reddit returns. After is the fullname to pass back via ListingOptions.After to fetch the next page ("" when the listing is exhausted).
type Post ¶
type Post struct {
ID string `json:"id"`
Fullname string `json:"name"` // e.g. "t3_abc123", used for paging/After
Title string `json:"title"`
Author string `json:"author"`
Subreddit string `json:"subreddit"`
Permalink string `json:"permalink"`
URL string `json:"url"`
Domain string `json:"domain"`
SelfText string `json:"selftext"`
Thumbnail string `json:"thumbnail"`
Score int `json:"score"`
Ups int `json:"ups"`
NumComments int `json:"num_comments"`
CreatedUTC float64 `json:"created_utc"`
IsSelf bool `json:"is_self"`
Over18 bool `json:"over_18"`
Stickied bool `json:"stickied"`
Flair string `json:"link_flair_text"`
}
Post is a single link or self-post ("t3" thing). Fields mirror the subset of Reddit's JSON that a reader UI needs; unmapped fields are dropped.
func (Post) FullPermalink ¶
FullPermalink joins the site-relative Permalink onto the canonical host so it is directly openable. Reddit's permalinks already begin with "/".
func (Post) HasThumbnail ¶
HasThumbnail reports whether Thumbnail is a real image URL rather than one of Reddit's sentinel strings ("self", "default", "nsfw", "spoiler", "").
type PostWithComments ¶
PostWithComments bundles a resolved post with its (partial) comment tree, as returned by the /comments/<id> endpoint.
type SubredditInfo ¶ added in v0.3.0
type SubredditInfo struct {
Name string // display_name, e.g. "golang" (subscribe as r/<Name>)
Title string // human title
PublicDescription string // short public blurb
Subscribers int64 // subscriber count
Over18 bool // NSFW flag
URL string // path, e.g. "/r/golang/"
Type string // subreddit_type: public / restricted / private
}
SubredditInfo is a subreddit's metadata as returned by the search and listing endpoints (a Reddit "t5" thing). It carries what a discovery UI needs to show a result and let the user subscribe by Name.
type SubredditPage ¶ added in v0.3.0
type SubredditPage struct {
Subreddits []SubredditInfo
After string
Before string
}
SubredditPage is a page of subreddit search results. After is the fullname to pass back via ListingOptions.After for the next page ("" when exhausted).