diff --git a/src/launcher.rs b/src/launcher.rs
index c4adc1e..1e59752 100644
--- a/src/launcher.rs
+++ b/src/launcher.rs
@@ -1,11 +1,12 @@
 use core::str;
-
-use crate::{config::LauncherConfig, minecraft::versions::VersionConfig};
-
+use std::sync::Arc;
+use tokio::sync::{mpsc, Mutex};
+use tokio::sync::mpsc::UnboundedReceiver;
+use crate::{config::LauncherConfig, minecraft::versions::VersionConfig, util};
 
 #[derive(Default)]
 pub struct Launcher {
-    pub config: LauncherConfig
+    pub config: LauncherConfig,
 }
 
 impl Launcher {
@@ -36,13 +37,28 @@ impl Launcher {
         self.save_config();
     }
 
-    pub async fn new_vanilla_instance(&self, config: VersionConfig) {
+    pub async fn new_vanilla_instance(&mut self, config: VersionConfig) -> UnboundedReceiver<(u8, String)> {
         let root = self.config.launcher_dir();
         let mut instances = root.clone();
         instances.push("instances");
         instances.push(config.id);
 
-        std::fs::create_dir_all(instances);
+        std::fs::create_dir_all(&instances);
+
+        instances.push("client.jar");
+
+        let (sx, rx) = mpsc::unbounded_channel();
+
+        let client_jar_url = config.downloads.client.url;
+
+        util::download_file(&client_jar_url, instances.to_str().unwrap(), config.downloads.client.size, sx);
+
+        /*for i in 0..config.libraries.len() {
+            let library = &config.libraries[i];
+
+        }*/
+
+        rx
     }
 
     pub fn init_dirs(&self) {
diff --git a/src/main.rs b/src/main.rs
index 7a0db90..f34d633 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -13,7 +13,7 @@ use winit::window::{Window, WindowId};
 use winit::event_loop::ActiveEventLoop;
 use wry::dpi::LogicalSize;
 use wry::http::{version, Request, Response};
-use wry::{RequestAsyncResponder, WebView, WebViewBuilder, WebViewBuilderExtWindows};
+use wry::{RequestAsyncResponder, WebView, WebViewBuilder};
 
 mod config;
 mod launcher;
@@ -76,6 +76,8 @@ async fn main() {
 
         let mut launcher = Launcher::default();
 
+        let mut dl_rec = None;
+
         loop {
             if let Some((ui_action, params, responder)) = receiver.recv().await {
                println!("Command: {}", ui_action);
@@ -129,7 +131,7 @@ async fn main() {
                                     Ok(config ) => {
                                         println!("Config: {}", config.id);
                                         responder.respond(Response::new(serde_json::to_vec(&UIMessage { params: vec!["show_loading".to_string()] }).unwrap()));
-                                        launcher.new_vanilla_instance(config).await;
+                                        dl_rec = Some(launcher.new_vanilla_instance(config).await);
                                     }
                                     Err(e) => {
                                         println!("Error: {}", e);
@@ -138,6 +140,11 @@ async fn main() {
                             }
                         }
                     }
+                    "check_download_status" => {
+                        if let Some((percent, text)) = dl_rec.unwrap().recv().await {
+                            responder.respond(Response::new(serde_json::to_vec(&UIMessage { params: vec!["update_downloads".to_string(), text, percent.to_string()] }).unwrap()));
+                        }
+                    }
                     _ => {}
                 }
             }
diff --git a/src/util.rs b/src/util.rs
index d523a12..73980d3 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -1,6 +1,10 @@
+use std::sync::{Arc, Mutex};
 use rand::{distr::Alphanumeric, Rng};
 use reqwest::{Client, Response};
 use tokio::{fs::File, io::AsyncWriteExt};
+use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender};
+use tokio::sync::{mpsc};
+use crate::launcher::Launcher;
 
 pub fn random_string(len: usize) -> String {
     rand::rng()
@@ -10,18 +14,26 @@ pub fn random_string(len: usize) -> String {
         .collect()
 }
 
-pub async fn download_file(url: &str, file_path: &str) -> Result<(), Box<dyn std::error::Error>> {
-    let client = Client::new();
-    let mut response: Response = client.get(url).send().await?;
-    
-    if response.status().is_success() {
-        let mut file = File::create(file_path).await?;
-        while let Some(chunk) = response.chunk().await? {
-            file.write_all(&chunk).await?;
-        }
-    } else {
-        println!("Failed to download file: {}", response.status());
-    }
+pub fn download_file(url: &str, file_path: &str, size: u64, sender: UnboundedSender<(u8, String)>) -> Result<(), Box<dyn std::error::Error>> {
+    let url = url.to_string();
+    let file_path = file_path.to_string();
+    tokio::spawn( async move {
+        let client = Client::new();
+        let mut response: Response = client.get(url).send().await.unwrap();
 
+        if response.status().is_success() {
+            let mut file = File::create(file_path).await.unwrap();
+            let mut cur_size = 0;
+            while let Some(chunk) = response.chunk().await.unwrap() {
+                cur_size += chunk.len();
+                sender.send((((cur_size / size as usize) * 100) as u8, "Downloading".to_string()) );
+                let _ = file.write_all(&chunk).await;
+            }
+        } else {
+            println!("Failed to download file: {}", response.status());
+        }
+    });
     Ok(())
-}
\ No newline at end of file
+}
+
+
diff --git a/src/www/portable.html b/src/www/portable.html
index cbc1583..dbcb12f 100644
--- a/src/www/portable.html
+++ b/src/www/portable.html
@@ -393,10 +393,21 @@
                 showAddSection();
               } else if( params[i] == "set_downloadable_versions" ) {
                 setDownloadableVersions(params.slice(1));
+                break;
+              } else if( params[i] == "update_downloads" ) {
+                  updateDownloads(params.slice(1));
+                  break;
               }
             }
           }
 
+          function updateDownloads(params) {
+              let text = params[0];
+              let percentage = params[1];
+              $("#loading-text").html(text);
+              $("#progress-bar").css("width", percentage+"%");
+          }
+
           function downloadSelectedVersion() {
             let version = $('#mc-version :selected').text();
             $.post({url: "download_vanilla", data: JSON.stringify({ params: [version] })}, processParams);
@@ -414,7 +425,7 @@
           }
 
           function signUp() {
-            $.post({url: "sign_up", data: JSON.stringify({ params: [$("#sign_up_username").val()] }) }, processParams)
+              $.post({url: "sign_up", data: JSON.stringify({params: [$("#sign_up_username").val()]})}, processParams)
           }
 
           function runPortable() {
@@ -442,7 +453,11 @@
           }
 
           $( document ).ready(async function() {
-            $.get("check_installation", processParams)
+            $.get("check_installation", processParams);
+
+            setInterval(function() {
+                $.get("check_download_status", processParams);
+            }, 200);
           });
       </script>
   </body>