diff --git a/controller/latest.js b/controller/latest.js
index 5ff748b..3924c77 100644
--- a/controller/latest.js
+++ b/controller/latest.js
@@ -1,24 +1,35 @@
 const { PrismaClient } =  require('@prisma/client')
+const redis = require('../utils/redis.js')
 const prisma = new PrismaClient()
 
 exports.getLatest = async (req, res) => {
-    res.json(await prisma.videos.findMany({
-        take: 30,
-        orderBy: [
-            {
-                archived: 'desc'
+    let json
+    const cached = await redis.get('latest')
+
+    if (cached) {
+        json = JSON.parse(cached)
+    } else {
+        json = await prisma.videos.findMany({
+            take: 90,
+            orderBy: [
+                {
+                    archived: 'desc'
+                }
+            ],
+            select: {
+                id: true,
+                title: true,
+                thumbnail: true,
+                published: true,
+                archived: true,
+                channel: true,
+                channelId: true,
+                channelAvatar: true,
+                channelVerified: true
             }
-        ],
-        select: {
-            id: true,
-            title: true,
-            thumbnail: true,
-            published: true,
-            archived: true,
-            channel: true,
-            channelId: true,
-            channelAvatar: true,
-            channelVerified: true
-        }
-    }))
+        })
+        await redis.set('latest', JSON.stringify(json), 'EX', 3600)
+    }
+
+    res.json(json)
 }
\ No newline at end of file
diff --git a/controller/search.js b/controller/search.js
index e6a7c9d..6b5e18a 100644
--- a/controller/search.js
+++ b/controller/search.js
@@ -1,8 +1,22 @@
+const crypto = require('node:crypto')
 const validate = require('../utils/validate.js')
+const redis = require('../utils/redis.js')
+const { RedisRateLimiter } = require('rolling-rate-limiter')
 const { PrismaClient } =  require('@prisma/client')
 const prisma = new PrismaClient()
 
+const limiter = new RedisRateLimiter({
+    client: redis, 
+    namespace: 'search:',
+    interval: 5 * 60 * 1000,
+    maxInInterval: 5
+})
+
 exports.searchVideo = async (req, res) => {
+    const ipHash = crypto.createHash('sha256').update(req.headers['x-userip'] || '0.0.0.0').digest('hex')
+    const isLimited = await limiter.limit(ipHash)
+    if (isLimited) return res.status(429).send('error-You have been ratelimited.')
+
     const id = await validate.validateVideoInput(req.query.search)
     if (id.fail) {
         const videos = await prisma.videos.findMany({
@@ -24,7 +38,7 @@ exports.searchPlaylist = async (req, res) => {
     if (id.fail) {
         res.status(500).send(id.message)
     } else {
-        res.send(``)
+        res.redirect(`${process.env.FRONTEND}/playlist?list=${id}`)
     }
 }
 
@@ -33,6 +47,6 @@ exports.searchChannel = async (req, res) => {
     if (id.fail) {
         res.status(500).send(id.message)
     } else {
-        res.send(``)
+        res.redirect(`${process.env.FRONTEND}/channel/${id}`)
     }
 }
\ No newline at end of file
diff --git a/controller/transparency.js b/controller/transparency.js
index e014334..554f038 100644
--- a/controller/transparency.js
+++ b/controller/transparency.js
@@ -1,14 +1,25 @@
 const { PrismaClient } =  require('@prisma/client')
+const redis = require('../utils/redis.js')
 const prisma = new PrismaClient()
 
 exports.getReports = async (req, res) => {
-    res.json((await prisma.reports.findMany()).map(r => {
-        return {
-            ...r,
-            details: (r.details).split('<').join('<').split('>').join('>'),
-            date: (r.date).toISOString().slice(0,10)
-        }
-    }))
+    let json
+    const cached = await redis.get('transparency')
+
+    if (cached) {
+        json = JSON.parse(cached)
+    } else {
+        json = (await prisma.reports.findMany()).map(r => {
+            return {
+                ...r,
+                details: (r.details).split('<').join('<').split('>').join('>'),
+                date: (r.date).toISOString().slice(0,10)
+            }
+        })
+        await redis.set('transparency', JSON.stringify(json), 'EX', 3600)
+    }
+
+    res.json(json)
 }
 
 exports.getReport = async (req, res) => {
diff --git a/controller/video.js b/controller/video.js
index 808abdc..e735ffe 100644
--- a/controller/video.js
+++ b/controller/video.js
@@ -3,28 +3,37 @@ const prisma = new PrismaClient()
 
 const DOMPurify = require('isomorphic-dompurify')
 const metadata = require('../utils/metadata.js')
+const redis = require('../utils/redis.js')
 
 exports.getVideo = async (req, res) => {
-    const info = await prisma.videos.findFirst({
-        where: {
-            id: req.params.id
-        },
-        select: {
-            title: true,
-            description: true,
-            thumbnail: true,
-            source: true,
-            published: true,
-            archived: true,
-            channel: true, 
-            channelId: true, 
-            channelAvatar: true,
-            channelVerified: true,
-            disabled: true
-        }
-    })
-    
-    if (!info) return res.json({ error: '404' })
+    let info
+    const cached = await redis.get(`video:${req.params.id}`)
+
+    if (cached) {
+        info = JSON.parse(cached)
+    } else {
+        info = await prisma.videos.findFirst({
+            where: {
+                id: req.params.id
+            },
+            select: {
+                title: true,
+                description: true,
+                thumbnail: true,
+                source: true,
+                published: true,
+                archived: true,
+                channel: true, 
+                channelId: true, 
+                channelAvatar: true,
+                channelVerified: true,
+                disabled: true
+            }
+        })
+        
+        if (!info) return res.json({ error: '404' })
+        await redis.set(`video:${req.params.id}`, JSON.stringify(info), 'EX', 3600)
+    }
 
     res.json({
         ...info,
@@ -33,11 +42,17 @@ exports.getVideo = async (req, res) => {
 }
 
 exports.getChannel = async (req, res) => {
-    const videos = await metadata.getChannelVideos(req.params.id)
-    const channel = await metadata.getChannel(req.params.id)
+    const cached = await redis.get(`channel:${req.params.id}`)
+    if (cached) return res.json(JSON.parse(cached))
 
-    if (!videos || !channel) return res.json({ error: '500' })
-    if (videos.error) return res.json({ error: '404' })
+    const [videos, channel] = await Promise.all([
+        metadata.getChannelVideos(req.params.id),
+        metadata.getChannel(req.params.id)
+    ])
+
+    if (!videos || !channel || videos.error) {
+        return res.json({ error: '404' });
+    }
 
     const archived = await prisma.videos.findMany({
         where: {
@@ -52,43 +67,66 @@ exports.getChannel = async (req, res) => {
         }
     })
 
-    var allVideos = []
-    allVideos = allVideos.concat((videos).map(video => {
-        return { 
-            id: video.url.replace('/watch?v=', ''),
-            published: (new Date(video.uploaded)).toISOString().slice(0,10),
-            ...video
-        }
-    }))
-
-    await Promise.all(archived.map(async (v) => {
-        const allVideo = allVideos.find(o => o.id == v.id)
-        if (allVideo) {
-            const index = allVideos.findIndex(o => o.id == v.id)
-            allVideos[index] = v
+    const processedVideos = videos.map(video => ({
+        id: video.url.replace('/watch?v=', ''),
+        published: new Date(video.uploaded).toISOString().slice(0, 10),
+        ...video
+    }));
+    
+    archived.forEach(v => {
+        const existingVideoIndex = processedVideos.findIndex(video => video.id === v.id);
+        if (existingVideoIndex !== -1) {
+            processedVideos[existingVideoIndex] = v;
         } else {
-            allVideos.push({
-                ...v, 
-                deleted: undefined
-            })
+            processedVideos.push({ ...v, deleted: undefined });
         }
-    }))
-
-    allVideos.sort((a, b) => new Date(b.published) - new Date(a.published))
-
-    res.json({
-        name: channel.author, 
+    });
+    
+    processedVideos.sort((a, b) => new Date(b.published) - new Date(a.published));
+    
+    const json = {
+        name: channel.author,
         avatar: channel.authorThumbnails[1].url,
         verified: channel.authorVerified,
-        videos: allVideos 
+        videos: processedVideos
+    }
+    await redis.set(`channel:${req.params.id}`, JSON.stringify(json), 'EX', 3600)
+    res.json(json)
+}
+
+exports.getOnlyChannelVideos = async (req, res) => {
+    const cached = await redis.get(`channelVideos:${req.params.id}`)
+    if (cached) return res.json(JSON.parse(cached))
+
+    const archived = await prisma.videos.findMany({
+        where: {
+            channelId: req.params.id
+        }, 
+        select: {
+            id: true,
+            title: true,
+            thumbnail: true,
+            published: true,
+            archived: true
+        },
+        orderBy: {
+            published: 'desc'
+        }
     })
+
+    const json = {
+        videos: archived 
+    }
+    await redis.set(`channelVideos:${req.params.id}`, JSON.stringify(json), 'EX', 3600)
+    res.json(json)
 }
 
 exports.getPlaylist = async (req, res) => {
+    const cached = await redis.get(`playlist:${req.params.id}`)
+    if (cached) return res.json(JSON.parse(cached))
+
     const playlist = await metadata.getPlaylistVideos(req.params.id)
-    
-    if (!playlist) return res.json({ error: '500' })
-    if (playlist.error) return res.json({ error: '404' })
+    if (!playlist || playlist.error) return res.json({ error: '404' })
 
     const playlistArchived = await prisma.videos.findMany({
         where: {
@@ -103,59 +141,54 @@ exports.getPlaylist = async (req, res) => {
         }
     })
 
-    var allVideos = []
-    allVideos = allVideos.concat((playlist.relatedStreams).map(video => {
-        return { 
-            id: video.url.replace('/watch?v=', ''),
-            published: (new Date(video.uploaded)).toISOString().slice(0,10),
-            ...video
-        }
-    }))
+    const allVideos = playlist.relatedStreams.map(video => ({
+        id: video.url.replace('/watch?v=', ''),
+        published: new Date(video.uploaded).toISOString().slice(0, 10),
+        ...video
+    }));
 
     await Promise.all(playlistArchived.map(async (v) => {
-        const allVideo = allVideos.find(o => o.id == v.id)
+        const allVideo = allVideos.find(o => o.id == v.id);
         if (allVideo) {
-            const index = allVideos.findIndex(o => o.id == v.id)
-            allVideos[index] = v
+            const index = allVideos.findIndex(o => o.id == v.id);
+            allVideos[index] = v;
         } else {
-            const live = await metadata.getVideoMetadata(v.id)
-
+            const live = await metadata.getVideoMetadata(v.id);
             allVideos.push({
-                ...v, 
+                ...v,
                 deleted: live.error ? true : false
-            })
+            });
         }
-    }))
-
-    await Promise.all(allVideos.map(async (v) => {
-        if (!v.archived) {
-            const video = await prisma.videos.findFirst({
-                where: {
-                    id: v.id
-                }, 
-                select: {
-                    id: true,
-                    title: true,
-                    thumbnail: true,
-                    published: true,
-                    archived: true
-                }
-            })
-
-            if (video) {
-                const index = allVideos.findIndex(o => o.id == v.id)
-                allVideos[index] = video
+    }));
+    
+    await Promise.all(allVideos.filter(v => !v.archived).map(async (v) => {
+        const video = await prisma.videos.findFirst({
+            where: {
+                id: v.id
+            },
+            select: {
+                id: true,
+                title: true,
+                thumbnail: true,
+                published: true,
+                archived: true
             }
+        });
+        if (video) {
+            const index = allVideos.findIndex(o => o.id == v.id);
+            allVideos[index] = video;
         }
-    }))
-
-    allVideos.sort((a, b) => new Date(a.published) - new Date(b.published))
-
-    res.json({
+    }));
+    
+    allVideos.sort((a, b) => new Date(b.published) - new Date(a.published));
+    
+    const json = {
         name: playlist.name,
-        channel: playlist.uploader, 
+        channel: playlist.uploader,
         url: playlist.uploaderUrl,
         avatar: playlist.uploaderAvatar,
-        videos: allVideos 
-    })
+        videos: allVideos
+    }
+    await redis.set(`playlist:${req.params.id}`, JSON.stringify(json), 'EX', 3600)
+    res.json(json)
 }
\ No newline at end of file
diff --git a/index.js b/index.js
index 809c958..e29fe1f 100644
--- a/index.js
+++ b/index.js
@@ -19,6 +19,7 @@ app.use(cors())
 app.get('/latest', latestController.getLatest)
 app.get('/video/:id', videoController.getVideo)
 app.get('/channel/:id', videoController.getChannel)
+app.get('/channel/:id/videos', videoController.getOnlyChannelVideos)
 app.get('/playlist/:id', videoController.getPlaylist)
 
 app.get('/search/video', searchController.searchVideo)
diff --git a/utils/ytdlp.js b/utils/ytdlp.js
index 17430bb..4852b5d 100644
--- a/utils/ytdlp.js
+++ b/utils/ytdlp.js
@@ -21,13 +21,13 @@ async function downloadVideo(url, ws) {
         })
 
         child.on("close", async (code, signal) => {
-            if (code == 2) {
+            if (code == 0) { // https://itsfoss.com/linux-exit-codes/
                 reject({
-                    fail: true
+                    fail: false
                 })
             } else {
                 resolve({
-                    fail: false
+                    fail: true
                 })
             }
         })