diff --git a/docs/supportedsites.md b/docs/supportedsites.md
index 5fddd1a5..8b7081e8 100644
--- a/docs/supportedsites.md
+++ b/docs/supportedsites.md
@@ -1231,6 +1231,12 @@ Consider all listed sites to potentially be NSFW.
Albums, Articles, Feeds, Images from Statuses, User Profiles, Videos |
|
+
+ | Whyp |
+ https://whyp.it/ |
+ Audio, Collections, User Profiles |
+ |
+
| WikiArt.org |
https://www.wikiart.org/ |
diff --git a/gallery_dl/extractor/__init__.py b/gallery_dl/extractor/__init__.py
index ae83e70e..9f182041 100644
--- a/gallery_dl/extractor/__init__.py
+++ b/gallery_dl/extractor/__init__.py
@@ -234,6 +234,7 @@ modules = [
"weebcentral",
"weebdex",
"weibo",
+ "whyp",
"wikiart",
"wikifeet",
"wikimedia",
diff --git a/gallery_dl/extractor/whyp.py b/gallery_dl/extractor/whyp.py
new file mode 100644
index 00000000..d5bc6abe
--- /dev/null
+++ b/gallery_dl/extractor/whyp.py
@@ -0,0 +1,98 @@
+# -*- coding: utf-8 -*-
+
+# Copyright 2025 Mike FΓ€hrmann
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+
+"""Extractors for https://whyp.it/"""
+
+from .common import Extractor, Message
+from .. import text
+
+BASE_PATTERN = r"(?:https?://)?(?:www\.)?whyp\.it"
+
+
+class WhypExtractor(Extractor):
+ """Base class for whyp extractors"""
+ category = "whyp"
+ root = "https://whyp.it"
+ root_api = "https://api.whyp.it"
+ directory_fmt = ("{category}", "{user[username]} ({user[id]})")
+ filename_fmt = "{id} {title}.{extension}"
+ archive_fmt = "{id}"
+
+ def _init(self):
+ self.headers_api = {
+ "Accept" : "application/json",
+ "Origin" : self.root,
+ "Referer": self.root + "/",
+ "Sec-Fetch-Dest": "empty",
+ "Sec-Fetch-Mode": "cors",
+ "Sec-Fetch-Site": "same-site",
+ }
+
+ def items(self):
+ for track in self.tracks():
+ if url := track.get("lossless_url"):
+ track["original"] = True
+ else:
+ url = track["lossy_url"]
+ track["original"] = False
+
+ if "created_at" in track:
+ track["date"] = self.parse_datetime_iso(track["created_at"])
+
+ yield Message.Directory, "", track
+ yield Message.Url, url, text.nameext_from_url(url, track)
+
+
+class WhypAudioExtractor(WhypExtractor):
+ subcategory = "audio"
+ pattern = BASE_PATTERN + r"/tracks/(\d+)"
+ example = "https://whyp.it/tracks/12345/SLUG"
+
+ def tracks(self):
+ url = f"{self.root_api}/api/tracks/{self.groups[0]}"
+ track = self.request_json(url, headers=self.headers_api)["track"]
+ return (track,)
+
+
+class WhypUserExtractor(WhypExtractor):
+ subcategory = "user"
+ pattern = BASE_PATTERN + r"/users/(\d+)"
+ example = "https://whyp.it/users/123/NAME"
+
+ def tracks(self):
+ url = f"{self.root_api}/api/users/{self.groups[0]}/tracks"
+ params = {}
+ headers = self.headers_api
+
+ while True:
+ data = self.request_json(url, params=params, headers=headers)
+
+ yield from data["tracks"]
+
+ if not (cursor := data.get("next_cursor")):
+ break
+ params["cursor"] = cursor
+
+
+class WhypCollectionExtractor(WhypExtractor):
+ subcategory = "collection"
+ pattern = BASE_PATTERN + r"/collections/(\d+)"
+ example = "https://whyp.it/collections/123/NAME"
+
+ def tracks(self):
+ cid = self.groups[0]
+
+ url = f"{self.root_api}/api/collections/{cid}"
+ headers = self.headers_api
+ self.kwdict["collection"] = collection = self.request_json(
+ url, headers=headers)["collection"]
+
+ url = f"{self.root_api}/api/collections/{cid}/tracks"
+ params = {"token": collection["token"]}
+ data = self.request_json(url, params=params, headers=headers)
+ return data["tracks"]
diff --git a/test/results/whyp.py b/test/results/whyp.py
new file mode 100644
index 00000000..49614f24
--- /dev/null
+++ b/test/results/whyp.py
@@ -0,0 +1,143 @@
+# -*- coding: utf-8 -*-
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+
+from gallery_dl.extractor import whyp
+
+
+__tests__ = (
+{
+ "#url" : "https://whyp.it/tracks/13721/fallout-3-intro-remake",
+ "#class" : whyp.WhypAudioExtractor,
+ "#pattern" : r"https://cdn.whyp.it/5e9de576-f33a-40ea-bd43-1693a568a6a0.mp3\?token=.+",
+
+ "allow_downloads": False,
+ "artwork_url" : None,
+ "artwork_url_fallback": "https://cdn.whyp.it/a46f3485-8d19-4753-98e0-76011c7e33b0.jpg",
+ "comments_count" : int,
+ "created_at" : "2025-11-24T16:59:50+00:00",
+ "date" : "dt:2025-11-24 16:59:50",
+ "description" : "",
+ "duration" : 46.34,
+ "extension" : "mp3",
+ "filename" : "5e9de576-f33a-40ea-bd43-1693a568a6a0",
+ "id" : 13721,
+ "lossless_size" : None,
+ "lossless_url" : None,
+ "lossy_size" : 1853719,
+ "lossy_url" : r"re:https://cdn.whyp.it/5e9de576-f33a-40ea-bd43-1693a568a6a0.mp3",
+ "original" : False,
+ "public" : True,
+ "settings_comments": "users",
+ "slug" : "fallout-3-intro-remake",
+ "title" : "Fallout 3 Intro Remake",
+ "token" : "k5E2z",
+ "user_id" : 1,
+ "waveform_url" : r"re:https://cdn.whyp.it/5e9de576-f33a-40ea-bd43-1693a568a6a0.json",
+ "user" : {
+ "avatar" : "https://cdn.whyp.it/a46f3485-8d19-4753-98e0-76011c7e33b0.jpg",
+ "has_enterprise" : True,
+ "has_pro" : True,
+ "has_pro_lifetime": False,
+ "id" : 1,
+ "slug" : "brad",
+ "status" : "Coding π¨π»βπ»",
+ "tracks_count" : 3,
+ "username" : "Brad",
+ },
+},
+
+{
+ "#url" : "https://whyp.it/users/1/brad",
+ "#class" : whyp.WhypUserExtractor,
+ "#pattern" : (
+ r"https://cdn.whyp.it/5e9de576-f33a-40ea-bd43-1693a568a6a0.mp3\?token=.+",
+ r"https://cdn.whyp.it/0d7a196b-3e1a-4510-a4a4-6189c56ecb27.flac\?token=.+",
+ r"https://cdn.whyp.it/3d134d07-7c55-4a6b-b321-56ce90ee1fc8.flac\?token=.+",
+ ),
+
+ "allow_downloads": bool,
+ "artwork_url" : {str, None},
+ "artwork_url_fallback": str,
+ "comments_count" : int,
+ "created_at" : "iso:dt",
+ "date" : "type:datetime",
+ "description" : str,
+ "duration" : float,
+ "extension" : {"mp3", "flac"},
+ "filename" : "iso:uuid",
+ "id" : {13721, 18337, 324260},
+ "lossless_size" : {int, None},
+ "lossless_url" : {str, None},
+ "lossy_size" : int,
+ "lossy_url" : str,
+ "original" : bool,
+ "public" : True,
+ "settings_comments": "users",
+ "slug" : str,
+ "title" : str,
+ "token" : str,
+ "user_id" : 1,
+ "waveform_url" : str,
+ "user" : {
+ "avatar" : "https://cdn.whyp.it/a46f3485-8d19-4753-98e0-76011c7e33b0.jpg",
+ "has_enterprise" : True,
+ "has_pro" : True,
+ "has_pro_lifetime": False,
+ "id" : 1,
+ "slug" : "brad",
+ "status" : "Coding π¨π»βπ»",
+ "tracks_count" : 3,
+ "username" : "Brad",
+ },
+},
+
+{
+ "#url" : "https://whyp.it/collections/1/example-collection",
+ "#class" : whyp.WhypCollectionExtractor,
+ "#pattern" : (
+ r"https://cdn.whyp.it/3d134d07-7c55-4a6b-b321-56ce90ee1fc8.flac\?token=.+",
+ r"https://cdn.whyp.it/0d7a196b-3e1a-4510-a4a4-6189c56ecb27.flac\?token=.+",
+ ),
+
+ "extension" : "flac",
+ "id" : {18337, 324260},
+ "original" : True,
+ "pivot_collection_id": 1,
+ "pivot_created_at": "iso:dt",
+ "pivot_order" : int,
+ "public" : True,
+ "collection" : {
+ "artwork_url" : "https://cdn.whyp.it/60fff341-02ef-4fe2-86f7-f283b2df1557.jpg",
+ "artwork_url_fallback": "https://cdn.whyp.it/b42b34d3-5839-4a26-9c32-41e917f31f6b.jpg",
+ "created_at" : "2023-07-20T16:14:33+00:00",
+ "description" : "This is an example collection on Whyp!",
+ "duration" : 352.59,
+ "hidden_tracks_count": 0,
+ "id" : 1,
+ "order" : 1,
+ "public" : True,
+ "slug" : "example-collection",
+ "title" : "Example Collection",
+ "token" : "VFc7Q",
+ "tracks_count": 2,
+ "updated_at" : "2025-11-17T19:45:01+00:00",
+ "user_id" : 1,
+ "user" : dict,
+ },
+ "user" : {
+ "avatar" : "https://cdn.whyp.it/a46f3485-8d19-4753-98e0-76011c7e33b0.jpg",
+ "has_enterprise" : True,
+ "has_pro" : True,
+ "has_pro_lifetime": False,
+ "id" : 1,
+ "slug" : "brad",
+ "status" : "Coding π¨π»βπ»",
+ "tracks_count" : 3,
+ "username" : "Brad",
+ },
+},
+
+)