diff --git a/locales/en-US.json b/locales/en-US.json
index 381bcab5..70a53e24 100644
--- a/locales/en-US.json
+++ b/locales/en-US.json
@@ -493,6 +493,7 @@
     "channel_tab_streams_label": "Livestreams",
     "channel_tab_podcasts_label": "Podcasts",
     "channel_tab_releases_label": "Releases",
+    "channel_tab_courses_label": "Courses",
     "channel_tab_playlists_label": "Playlists",
     "channel_tab_community_label": "Community",
     "channel_tab_channels_label": "Channels",
diff --git a/src/invidious/channels/playlists.cr b/src/invidious/channels/playlists.cr
index 91029fe3..9b45d0c8 100644
--- a/src/invidious/channels/playlists.cr
+++ b/src/invidious/channels/playlists.cr
@@ -44,3 +44,12 @@ def fetch_channel_releases(ucid, author, continuation)
   end
   return extract_items(initial_data, author, ucid)
 end
+
+def fetch_channel_courses(ucid, author, continuation)
+  if continuation
+    initial_data = YoutubeAPI.browse(continuation)
+  else
+    initial_data = YoutubeAPI.browse(ucid, params: "Egdjb3Vyc2Vz8gYFCgPCAQA%3D")
+  end
+  return extract_items(initial_data, author, ucid)
+end
diff --git a/src/invidious/frontend/channel_page.cr b/src/invidious/frontend/channel_page.cr
index fe7d6d6e..ee7ebe48 100644
--- a/src/invidious/frontend/channel_page.cr
+++ b/src/invidious/frontend/channel_page.cr
@@ -7,6 +7,7 @@ module Invidious::Frontend::ChannelPage
     Streams
     Podcasts
     Releases
+    Courses
     Playlists
     Community
     Channels
diff --git a/src/invidious/routes/api/v1/channels.cr b/src/invidious/routes/api/v1/channels.cr
index 588bbc2a..a940ee68 100644
--- a/src/invidious/routes/api/v1/channels.cr
+++ b/src/invidious/routes/api/v1/channels.cr
@@ -368,6 +368,35 @@ module Invidious::Routes::API::V1::Channels
     end
   end
 
+  def self.courses(env)
+    locale = env.get("preferences").as(Preferences).locale
+
+    env.response.content_type = "application/json"
+
+    ucid = env.params.url["ucid"]
+    continuation = env.params.query["continuation"]?
+
+    # Use the macro defined above
+    channel = nil # Make the compiler happy
+    get_channel()
+
+    items, next_continuation = fetch_channel_courses(channel.ucid, channel.author, continuation)
+
+    JSON.build do |json|
+      json.object do
+        json.field "playlists" do
+          json.array do
+            items.each do |item|
+              item.to_json(locale, json) if item.is_a?(SearchPlaylist)
+            end
+          end
+        end
+
+        json.field "continuation", next_continuation if next_continuation
+      end
+    end
+  end
+
   def self.community(env)
     locale = env.get("preferences").as(Preferences).locale
 
diff --git a/src/invidious/routes/channels.cr b/src/invidious/routes/channels.cr
index 7d634cbb..9f280251 100644
--- a/src/invidious/routes/channels.cr
+++ b/src/invidious/routes/channels.cr
@@ -197,6 +197,26 @@ module Invidious::Routes::Channels
     templated "channel"
   end
 
+  def self.courses(env)
+    data = self.fetch_basic_information(env)
+    return data if !data.is_a?(Tuple)
+
+    locale, user, subscriptions, continuation, ucid, channel = data
+
+    sort_by = ""
+    sort_options = [] of String
+
+    items, next_continuation = fetch_channel_courses(
+      channel.ucid, channel.author, continuation
+    )
+
+    items = items.select(SearchPlaylist)
+    items.each(&.author = "")
+
+    selected_tab = Frontend::ChannelPage::TabsAvailable::Courses
+    templated "channel"
+  end
+
   def self.community(env)
     data = self.fetch_basic_information(env)
     if !data.is_a?(Tuple)
@@ -307,7 +327,7 @@ module Invidious::Routes::Channels
 
   private KNOWN_TABS = {
     "home", "videos", "shorts", "streams", "podcasts",
-    "releases", "playlists", "community", "channels", "about",
+    "releases", "courses", "playlists", "community", "channels", "about",
   }
 
   # Redirects brand url channels to a normal /channel/:ucid route
diff --git a/src/invidious/routing.cr b/src/invidious/routing.cr
index 902e0a30..c3d6cd41 100644
--- a/src/invidious/routing.cr
+++ b/src/invidious/routing.cr
@@ -120,6 +120,7 @@ module Invidious::Routing
     get "/channel/:ucid/streams", Routes::Channels, :streams
     get "/channel/:ucid/podcasts", Routes::Channels, :podcasts
     get "/channel/:ucid/releases", Routes::Channels, :releases
+    get "/channel/:ucid/courses", Routes::Channels, :courses
     get "/channel/:ucid/playlists", Routes::Channels, :playlists
     get "/channel/:ucid/community", Routes::Channels, :community
     get "/channel/:ucid/channels", Routes::Channels, :channels
@@ -250,6 +251,7 @@ module Invidious::Routing
       get "/api/v1/channels/:ucid/streams", {{namespace}}::Channels, :streams
       get "/api/v1/channels/:ucid/podcasts", {{namespace}}::Channels, :podcasts
       get "/api/v1/channels/:ucid/releases", {{namespace}}::Channels, :releases
+      get "/api/v1/channels/:ucid/courses", {{namespace}}::Channels, :courses
       get "/api/v1/channels/:ucid/playlists", {{namespace}}::Channels, :playlists
       get "/api/v1/channels/:ucid/community", {{namespace}}::Channels, :community
       get "/api/v1/channels/:ucid/channels", {{namespace}}::Channels, :channels
diff --git a/src/invidious/views/channel.ecr b/src/invidious/views/channel.ecr
index 1fe8ab7e..686de6bd 100644
--- a/src/invidious/views/channel.ecr
+++ b/src/invidious/views/channel.ecr
@@ -11,6 +11,7 @@
     when .channels?  then "/channel/#{ucid}/channels"
     when .podcasts?  then "/channel/#{ucid}/podcasts"
     when .releases?  then "/channel/#{ucid}/releases"
+    when .courses? then "/channel/#{ucid}/courses"
     else
       "/channel/#{ucid}"
     end