{"id":22080562,"url":"https://github.com/electronic-mango/reddit-fastapi-api","last_synced_at":"2026-04-22T23:36:07.228Z","repository":{"id":232471141,"uuid":"784221315","full_name":"Electronic-Mango/reddit-fastapi-api","owner":"Electronic-Mango","description":"Simple API for Reddit API.","archived":false,"fork":false,"pushed_at":"2024-06-15T14:59:27.000Z","size":173,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-20T18:49:54.346Z","etag":null,"topics":["api","api-rest","fastapi","python","python3","reddit","reddit-api"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Electronic-Mango.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-04-09T12:31:30.000Z","updated_at":"2024-06-15T14:59:30.000Z","dependencies_parsed_at":"2024-04-15T18:38:10.044Z","dependency_job_id":null,"html_url":"https://github.com/Electronic-Mango/reddit-fastapi-api","commit_stats":null,"previous_names":["electronic-mango/reddit-fastapi-api"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Electronic-Mango/reddit-fastapi-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Electronic-Mango%2Freddit-fastapi-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Electronic-Mango%2Freddit-fastapi-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Electronic-Mango%2Freddit-fastapi-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Electronic-Mango%2Freddit-fastapi-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Electronic-Mango","download_url":"https://codeload.github.com/Electronic-Mango/reddit-fastapi-api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Electronic-Mango%2Freddit-fastapi-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32159959,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-22T17:06:48.269Z","status":"ssl_error","status_checked_at":"2026-04-22T17:06:19.037Z","response_time":58,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","api-rest","fastapi","python","python3","reddit","reddit-api"],"created_at":"2024-11-30T23:15:46.892Z","updated_at":"2026-04-22T23:36:07.207Z","avatar_url":"https://github.com/Electronic-Mango.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Reddit API API\n\n[![CodeQL](https://github.com/Electronic-Mango/reddit-fastapi-api/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/Electronic-Mango/reddit-fastapi-api/actions/workflows/codeql-analysis.yml)\n[![Black](https://github.com/Electronic-Mango/reddit-fastapi-api/actions/workflows/black.yml/badge.svg)](https://github.com/Electronic-Mango/reddit-fastapi-api/actions/workflows/black.yml)\n[![Flake8](https://github.com/Electronic-Mango/reddit-fastapi-api/actions/workflows/flake8.yml/badge.svg)](https://github.com/Electronic-Mango/reddit-fastapi-api/actions/workflows/flake8.yml)\n\nA simple Reddit REST API allowing accessing both subreddit and user articles,\nbuild with [`FastAPI`](https://fastapi.tiangolo.com/) and my [`Reddit Python API`](https://github.com/Electronic-Mango/reddit-python-api)!\n\n\n\n## Table of contents\n\n - [Introduction and requirements](#introduction-and-requirements)\n - [Configuration](#configuration)\n   - [API parameters](#api-parameters)\n   - [Reddit app \u0026 required parameters](#reddit-app--required-parameters)\n   - [Docker](#docker)\n - [Additional authorization](#additional-authorization)\n - [Running the API](#running-the-api)\n   - [From source](#from-source)\n   - [Docker](#docker-1)\n - [API endpoints](#api-endpoints)\n   - [Get a list of articles from a subreddit](#get-a-list-of-articles-from-a-subreddit)\n   - [Get one random article from a subreddit](#get-one-random-article-from-a-subreddit)\n   - [Get a list of articles from a Reddit user](#get-a-list-of-articles-from-a-reddit-user)\n   - [Get a random article from a Reddit user](#get-a-random-article-from-a-reddit-user)\n - [Filtering and article types](#filtering-and-article-types)\n   - [Reddit galleries](#reddit-galleries)\n - [Load count](#load-count)\n - [Disclaimer](#disclaimer)\n\n\n\n## Introduction and requirements\n\nThis REST API was built using [`FastAPI`](https://fastapi.tiangolo.com/), my [`Reddit Python API`](https://github.com/Electronic-Mango/reddit-python-api)  and `Python 3.11`.\nPython version at least `3.11` is required.\n\nFull list of Python requirements is in `requirements.txt` file.\n\nTechnically this API only *wraps* parts of official Reddit API, thus *Reddit API **API***.\nHowever, accessing Reddit API itself through external services is quite cumbersome, due to necessary OAuth 2.0 authorization.\nThis API allows external services to access API through simple HTTP requests, without worrying about access tokens, Reddit app client, etc.\nIt also allows for simple access to specific services, like reading only one random article or reading only media or text articles, without any additional processing.\n\nThis API uses my simple [`Reddit Python API`](https://github.com/Electronic-Mango/reddit-python-api) to access official Reddit API.\n\nNo data is stored by the API.\nReddit is accessed in `read-only` mode.\nAPI requests can optionally be authenticated based on request header.\n\nYou can check my other repository [Memes Discord bot Docker deployment](https://github.com/Electronic-Mango/memes-discord-bot-docker-deployment) for an example of how you can use this API in a Discord bot, deployed via Docker Compose.\n\n\n\n## Configuration\n\n### API parameters\n\nAPI configuration can be done through a YAML configuration file.\nBy default `settings.yml` from the project root is used, which has some sensible defaults, other than [Reddit API client ID and secret](#reddit-app--required-parameters).\n\nYou can overwrite values from default `settings.yml` by providing a custom one under path from `CUSTOM_SETTINGS_PATH` environment variable.\nIn this custom YAML you can provide only parameters which you want to overwrite.\nIf parameter is absent in the custom one, then default value from `settings.yml` will be used.\n\nValue for `CUSTOM_SETTINGS_PATH` can also be provided via `.env` file in the project root.\n\n\n### Reddit app \u0026 required parameters\n\nTo run the API you need to first register a Reddit app at https://old.reddit.com/prefs/apps/.\nThere are two fields which need to be filled in `reddit` - `client` section in `settings.yml` based on your app - `id` and `secret`.\nThose values will be used to acquire OAuth 2.0 token from Reddit API itself. \n\nNo other data is necessary, since the API works in `read-only` mode.\n\n\n### Docker\n\nThere's a `Dockerfile` in the repo, which will build a Docker image for the API using `python:3.12-alpine` as base.\nYou can set all configuration parameters using environment variables for Docker container, rather than modifying project files before building.\n\nYou can also use `docker-compose.yml` to build and start the container via:\n\n```\ndocker compose up -d --build\n```\n\nCompose allows using `custom_settings.yml` in project root for custom configuration, like [Reddit app ID and secret](#reddit-app--required-parameters) without modifying project files.\nBy default, this file will be loaded into the image, along with all `.yml` files from the project root.\n\nYou can get around this by modifying value of `CUSTOM_SETTINGS_PATH` in `docker-compose.yml` to point to a file in a mounted volume.\n\nDefault port where API requests are handled is `8080`, which is mapped to local port `3001`.\n\n\n\n## Additional authorization\n\nApi has a basic authorization mechanism based on API key send as request header, separate from Reddit API OAuth 2.0.\nYou can set API key header name and expected value in `settings.yml` in `api` - `authorization_header` - `name` and `expected_value`.\n\nIf either of them is empty authorization will be disabled and all requests will be accepted.\n\nIf both fields are filled, then any request which doesn't have a header named `name` with value `expected_value` will be rejected with code `401`.\n\nBy default, without any changes to `settings.yml` authorization is disabled.\n\n\n\n## Running the API\n\nFirst you need to register a Reddit app and note its ID and secret.\n\n\n###  From source\n\n 1. Install all packages from `requirements.txt`\n 2. Fill Reddit app ID and secret either in `settings.yml` or in a custom one\n 3. Run `src/main.py` via Python\n\n\n### Docker\n\n 1. Fill Reddit app ID and secret in `settings.yml` or in `custom_settings.yml`\n 2. Run `docker compose up -d --build`\n\nYou can skip `--build` flag on subsequent runs if you didn't change the source code, but keep in mind that by default `custom_settings.yml` is added to the docker image.\nAny changes there will require image rebuild.\n\nYou can get around this by modifying value of `CUSTOM_SETTINGS_PATH` in `docker-compose.yml` to point to a file in a mounted volume.\n\n\n\n## API endpoints\n\n\u003e [!NOTE]\n\u003e Description of all endpoint, schemas, etc. can be accessed through swagger (`/docs`), or redoc (`/redoc`).\n\nAll endpoints are accessible via `GET` requests.\nIf request authorization is configured incoming requests needs to have correct header and its value.\n\nEach endpoint has a single path parameter and series of optional query parameters.\nQuery parameters are the same across all endpoints.\n\n### Get a list of articles from a subreddit\n\n```\n/subreddit/list/{subreddit}\n```\n\n`subreddit` path parameter specifies which subreddit should be accessed.\n\nQuery parameters:\n * `sort` - Which Reddit sorting type to use when loading articles\n * `time` - Time period in which articles should be accessed\n * `count` - How many articles will be loaded, Reddit API uses 25 by default\n * `article_type` - Define whether to load all articles, only text or only images\n\n`sort` can be one of the following:\n - `hot` - used by default\n - `new`\n - `rising`\n - `top`\n - `controversial`\n\n`time` can be one of the following:\n - `hour`\n - `day`\n - `week`\n - `month`\n - `year`\n - `all`\n\n`article_type` can be one of the following:\n - `all` - all articles\n - `media` - only media articles\n - `text` - only articles where `selftext` is not empty\n\n\nExample request:\n```\nGET /subreddit/list/wholesomememes?count=3\u0026sort=top\n```\n\nExample response:\n```json\n{\n  \"count\": 3,\n  \"articles\": [\n    {\n      \"id\": \"1c0egcz\",\n      \"url\": \"https://i.redd.it/29nc1eq3eltc1.jpeg\",\n      \"title\": \"always true\",\n      \"author\": \"jeremyvi\",\n      \"nsfw\": false,\n      \"spoiler\": false,\n      \"selftext\": \"\",\n      \"score\": 18433,\n      \"created_utc\": \"2024-04-10T08:00:16\",\n      \"permalink\": \"/r/wholesomememes/comments/1c0egcz/always_true/\",\n      \"subreddit\": \"wholesomememes\",\n      \"stickied\": false,\n      \"media_url\": \"https://i.redd.it/29nc1eq3eltc1.jpeg\"\n    },\n    {\n      \"id\": \"1c0kt45\",\n      \"url\": \"https://i.redd.it/x16ms4i9fntc1.png\",\n      \"title\": \"I wants to pet him\",\n      \"author\": \"Puzzleheaded-Slip203\",\n      \"nsfw\": false,\n      \"spoiler\": false,\n      \"selftext\": \"\",\n      \"score\": 12015,\n      \"created_utc\": \"2024-04-10T14:50:34\",\n      \"permalink\": \"/r/wholesomememes/comments/1c0kt45/i_wants_to_pet_him/\",\n      \"subreddit\": \"wholesomememes\",\n      \"stickied\": false,\n      \"media_url\": \"https://i.redd.it/x16ms4i9fntc1.png\"\n    },\n    {\n      \"id\": \"1c0cv7h\",\n      \"url\": \"https://i.redd.it/64qvbwu4xktc1.jpeg\",\n      \"title\": \"I wanna be a weather reporter too\",\n      \"author\": \"dyerama6\",\n      \"nsfw\": false,\n      \"spoiler\": false,\n      \"selftext\": \"\",\n      \"score\": 7515,\n      \"created_utc\": \"2024-04-10T06:25:11\",\n      \"permalink\": \"/r/wholesomememes/comments/1c0cv7h/i_wanna_be_a_weather_reporter_too/\",\n      \"subreddit\": \"wholesomememes\",\n      \"stickied\": false,\n      \"media_url\": \"https://i.redd.it/64qvbwu4xktc1.jpeg\"\n    }\n  ]\n}\n```\n\n\n### Get one random article from a subreddit\n\n```\n/subreddit/random/{subreddit}\n```\n\n`subreddit` path parameter specifies which subreddit should be accessed.\n\nAll query query parameters are the same as for [loading a list of articles for a subreddit](#get-a-list-of-articles-from-a-subreddit).\n\n`count` determines how many articles will be loaded, a random one will be selected from them.\n\n\nExample request:\n```\nGET /subreddit/random/explainlikeimfive?count=100\u0026sort=top\u0026article_type=text\n```\n\nExample response:\n```json\n{\n  \"id\": \"1c05ako\",\n  \"url\": \"https://www.reddit.com/r/explainlikeimfive/comments/1c05ako/eli5_why_was_purple_dye_so_rare_historically/\",\n  \"title\": \"ELI5: Why was purple dye so rare historically?\",\n  \"author\": \"Inside-Honeydew9785\",\n  \"nsfw\": false,\n  \"spoiler\": false,\n  \"selftext\": \"I know natural purple itself was difficult to obtain, but why didn’t they just mix red and blue? Were those also rare? Did it just not work?\",\n  \"score\": 610,\n  \"created_utc\": \"2024-04-10T00:28:23\",\n  \"permalink\": \"/r/explainlikeimfive/comments/1c05ako/eli5_why_was_purple_dye_so_rare_historically/\",\n  \"subreddit\": \"explainlikeimfive\",\n  \"stickied\": false,\n  \"media_url\": null\n}\n```\n\n\n### Get a list of articles from a Reddit user\n\n```\n/user/list/{username}\n```\n\n`username` path parameter specifies which user's submissions should be accessed.\n\nAll query parameters are the same as for [loading a list of articles for a subreddit](#get-a-list-of-articles-from-a-subreddit).\n\nExample request:\n```\nGET /user/list/cme_t?count=4\u0026article_type=media\u0026time=year\n```\n\nExample response:\n```json\n{\n  \"count\": 2,\n  \"articles\": [\n    {\n      \"id\": \"1bwm2xo\",\n      \"url\": \"https://i.redd.it/htb0twxhrosc1.jpeg\",\n      \"title\": \"[OC][Art] The Weekly Roll Ch.150. ”One-Fifty, Baby!”\",\n      \"author\": \"CME_T\",\n      \"nsfw\": false,\n      \"spoiler\": false,\n      \"selftext\": \"\",\n      \"score\": 420,\n      \"created_utc\": \"2024-04-05T18:16:35\",\n      \"permalink\": \"/r/DnD/comments/1bwm2xo/ocart_the_weekly_roll_ch150_onefifty_baby/\",\n      \"subreddit\": \"DnD\",\n      \"stickied\": false,\n      \"media_url\": \"https://i.redd.it/htb0twxhrosc1.jpeg\"\n    },\n    {\n      \"id\": \"1bviskx\",\n      \"url\": \"https://i.redd.it/7v823myvkfsc1.jpeg\",\n      \"title\": \"[OC] The Weekly Roll Ch. 150. \\\"One-Fifty, Baby!\\\"\",\n      \"author\": \"CME_T\",\n      \"nsfw\": false,\n      \"spoiler\": false,\n      \"selftext\": \"\",\n      \"score\": 4154,\n      \"created_utc\": \"2024-04-04T11:23:58\",\n      \"permalink\": \"/r/dndmemes/comments/1bviskx/oc_the_weekly_roll_ch_150_onefifty_baby/\",\n      \"subreddit\": \"dndmemes\",\n      \"stickied\": false,\n      \"media_url\": \"https://i.redd.it/7v823myvkfsc1.jpeg\"\n    }\n  ]\n}\n```\n\nNotice that 4 media articles were requested, but response only contains 2.\nIt's because out of 4 loaded articles only 2 were images.\n\n\n### Get a random article from a Reddit user\n\nEndpoint:\n```\n/user/random/{username}\n```\n\n`username` path parameter specifies which user's submissions should be accessed.\n\nAll query parameters are the same as for [loading a list of articles for a subreddit](#get-a-list-of-articles-from-a-subreddit).\n\n`count` determines how many articles will be loaded, a random one will be selected from them.\n\nExample request:\n```\nGET /user/random/cme_t?article_type=media\n```\n\nExample response:\n```json\n{\n  \"id\": \"1bk228v\",\n  \"url\": \"https://i.redd.it/grjrcu98jnpc1.jpeg\",\n  \"title\": \"The Weekly Roll Ch. 149. \\\"WHAT DAY IS IT?!\\\"\",\n  \"author\": \"CME_T\",\n  \"nsfw\": false,\n  \"spoiler\": false,\n  \"selftext\": \"\",\n  \"score\": 1529,\n  \"created_utc\": \"2024-03-21T09:56:03\",\n  \"permalink\": \"/r/TheWeeklyRoll/comments/1bk228v/the_weekly_roll_ch_149_what_day_is_it/\",\n  \"subreddit\": \"TheWeeklyRoll\",\n  \"stickied\": false,\n  \"media_url\": \"https://i.redd.it/grjrcu98jnpc1.jpeg\"\n}\n```\n\n\n\n## Filtering and article types\n\nOther than all articles, API allows for filtering article types.\nThe two filters are `text` and `media`.\n\nFor `text` all articles where `selftext` is not empty are selected.\n\nFor `media` there are two cases, one for images and one for videos:\n\n - images are detected based on `i.redd.it` domain **OR** `post_hint` equal to `image`, since not all subreddits have `post_hint`\n - videos are detected based on `v.redd.it` domain **AND** `is_video` equal to `True`, there are some posts where domain is `v.redd.it`, but there are no necessary URLs\n\nIn case of videos, resulting `media_url` URL has `?source=fallback` trimmed out, so it ends with file extension.\n\n\n### Reddit galleries\n\nCurrently, galleries won't be filtered into `media` category and their media URLs aren't easily accessible.\n\n\n\n## Load count\n\nWhen specifying how many articles should be loaded the final count can be lower.\n\nFor all articles this can occur if a given subreddit or user has fewer articles than specified.\n\nFor text and media articles the passed value only determines how many articles are loaded from Reddit overall.\nThis value can be later lowered as only specific type of articles are filtered from the list of all articles.\nNot additional articles are loaded after filtering.\n\nLoad count also impacts retrieving one random article.\nThis one random article is picked from a loaded selection, instead of sending all of them.\nActual count of articles to pick from can be lowered due to additional filtering, as before.\n\nStill, the higher the load count the lower the odds of selecting the same random article on subsequent API calls.\n\n\n\n## Disclaimer\n\nThis bot is in no way affiliated, associated, authorized, endorsed by, or in any way officially connected with Reddit.\nThis is an independent and unofficial project.\nUse at your own risk.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felectronic-mango%2Freddit-fastapi-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felectronic-mango%2Freddit-fastapi-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felectronic-mango%2Freddit-fastapi-api/lists"}