diff --git a/validation/src/create.rs b/validation/src/create.rs
index 76d8ccf..9db62a8 100644
--- a/validation/src/create.rs
+++ b/validation/src/create.rs
@@ -1,3 +1,4 @@
+use crate::download::download_asset_version;
 use crate::rbx_util::{get_root_instance,get_mapinfo,read_dom,MapInfo,ReadDomError,GetRootInstanceError,ParseGameIDError};
 
 #[allow(dead_code)]
@@ -5,11 +6,9 @@ use crate::rbx_util::{get_root_instance,get_mapinfo,read_dom,MapInfo,ReadDomErro
 pub enum Error{
 	CreatorTypeMustBeUser,
 	ModelInfoDownload(rbx_asset::cloud::GetError),
-	ModelLocationDownload(rbx_asset::cloud::GetError),
-	NonFreeModel,
-	ModelFileDownload(rbx_asset::cloud::GetError),
 	ParseUserID(core::num::ParseIntError),
 	ParseModelVersion(core::num::ParseIntError),
+	Download(crate::download::Error),
 	ModelFileDecode(ReadDomError),
 	GetRootInstance(GetRootInstanceError),
 	ParseGameID(ParseGameIDError),
@@ -49,19 +48,11 @@ impl crate::message_handler::MessageHandler{
 		let user_id:u64=user_id_string.parse().map_err(Error::ParseUserID)?;
 		let asset_version=info.revisionId.parse().map_err(Error::ParseModelVersion)?;
 
-		// download the location of the map model
-		let location=self.cloud_context.get_asset_version_location(rbx_asset::cloud::GetAssetVersionRequest{
+		// download the map model
+		let model_data=download_asset_version(&self.cloud_context,rbx_asset::cloud::GetAssetVersionRequest{
 			asset_id:create_info.ModelID,
 			version:asset_version,
-		}).await.map_err(Error::ModelLocationDownload)?;
-
-		// if the location does not exist, you are not allowed to donwload it
-		let Some(location)=location.location else{
-			return Err(Error::NonFreeModel);
-		};
-
-		// download the map model
-		let model_data=self.cloud_context.get_asset(&location).await.map_err(Error::ModelFileDownload)?;
+		}).await.map_err(Error::Download)?;
 
 		// decode dom (slow!)
 		let dom=read_dom(std::io::Cursor::new(model_data)).map_err(Error::ModelFileDecode)?;
diff --git a/validation/src/download.rs b/validation/src/download.rs
new file mode 100644
index 0000000..202be72
--- /dev/null
+++ b/validation/src/download.rs
@@ -0,0 +1,26 @@
+#[allow(dead_code)]
+#[derive(Debug)]
+pub enum Error{
+	ModelLocationDownload(rbx_asset::cloud::GetError),
+	NonFreeModel,
+	ModelFileDownload(rbx_asset::cloud::GetError),
+}
+impl std::fmt::Display for Error{
+	fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
+		write!(f,"{self:?}")
+	}
+}
+impl std::error::Error for Error{}
+
+pub async fn download_asset_version(cloud_context:&rbx_asset::cloud::Context,request:rbx_asset::cloud::GetAssetVersionRequest)->Result<Vec<u8>,Error>{
+	// download the location of the map model
+	let location=cloud_context.get_asset_version_location(request).await.map_err(Error::ModelLocationDownload)?;
+
+	// if the location does not exist, you are not allowed to download it
+	let location=location.location.ok_or(Error::NonFreeModel)?;
+
+	// download the map model
+	let model_data=cloud_context.get_asset(&location).await.map_err(Error::ModelFileDownload)?;
+
+	Ok(model_data)
+}
diff --git a/validation/src/main.rs b/validation/src/main.rs
index 00fb7f3..2b91fdc 100644
--- a/validation/src/main.rs
+++ b/validation/src/main.rs
@@ -4,6 +4,7 @@ mod rbx_util;
 mod message_handler;
 mod nats_types;
 mod types;
+mod download;
 mod create;
 mod create_mapfix;
 mod create_submission;
diff --git a/validation/src/upload_mapfix.rs b/validation/src/upload_mapfix.rs
index 8df288a..b74e562 100644
--- a/validation/src/upload_mapfix.rs
+++ b/validation/src/upload_mapfix.rs
@@ -1,11 +1,10 @@
+use crate::download::download_asset_version;
 use crate::nats_types::UploadMapfixRequest;
 
 #[allow(dead_code)]
 #[derive(Debug)]
 pub enum Error{
-	GetLocation(rbx_asset::cloud::GetError),
-	NonFreeModel,
-	Get(rbx_asset::cloud::GetError),
+	Download(crate::download::Error),
 	Json(serde_json::Error),
 	Upload(rbx_asset::cookie::UploadError),
 	ApiActionMapfixUploaded(submissions_api::Error),
@@ -19,19 +18,11 @@ impl std::error::Error for Error{}
 
 impl crate::message_handler::MessageHandler{
 	pub async fn upload_mapfix(&self,upload_info:UploadMapfixRequest)->Result<(),Error>{
-		// download the location of the map model
-		let location=self.cloud_context.get_asset_version_location(rbx_asset::cloud::GetAssetVersionRequest{
+		// download the map model
+		let model_data=download_asset_version(&self.cloud_context,rbx_asset::cloud::GetAssetVersionRequest{
 			asset_id:upload_info.ModelID,
 			version:upload_info.ModelVersion,
-		}).await.map_err(Error::GetLocation)?;
-
-		// if the location does not exist, you are not allowed to donwload it
-		let Some(location)=location.location else{
-			return Err(Error::NonFreeModel);
-		};
-
-		// download the map model
-		let model_data=self.cloud_context.get_asset(&location).await.map_err(Error::Get)?;
+		}).await.map_err(Error::Download)?;
 
 		// upload the map to the strafesnet group
 		let _upload_response=self.cookie_context.upload(rbx_asset::cookie::UploadRequest{
diff --git a/validation/src/upload_submission.rs b/validation/src/upload_submission.rs
index 9b9cc50..9052433 100644
--- a/validation/src/upload_submission.rs
+++ b/validation/src/upload_submission.rs
@@ -1,11 +1,10 @@
+use crate::download::download_asset_version;
 use crate::nats_types::UploadSubmissionRequest;
 
 #[allow(dead_code)]
 #[derive(Debug)]
 pub enum Error{
-	GetLocation(rbx_asset::cloud::GetError),
-	NonFreeModel,
-	Get(rbx_asset::cloud::GetError),
+	Download(crate::download::Error),
 	Json(serde_json::Error),
 	Create(rbx_asset::cookie::CreateError),
 	SystemTime(std::time::SystemTimeError),
@@ -20,19 +19,11 @@ impl std::error::Error for Error{}
 
 impl crate::message_handler::MessageHandler{
 	pub async fn upload_submission(&self,upload_info:UploadSubmissionRequest)->Result<(),Error>{
-		// download the location of the map model
-		let location=self.cloud_context.get_asset_version_location(rbx_asset::cloud::GetAssetVersionRequest{
+		// download the map model
+		let model_data=download_asset_version(&self.cloud_context,rbx_asset::cloud::GetAssetVersionRequest{
 			asset_id:upload_info.ModelID,
 			version:upload_info.ModelVersion,
-		}).await.map_err(Error::GetLocation)?;
-
-		// if the location does not exist, you are not allowed to donwload it
-		let Some(location)=location.location else{
-			return Err(Error::NonFreeModel);
-		};
-
-		// download the map model
-		let model_data=self.cloud_context.get_asset(&location).await.map_err(Error::Get)?;
+		}).await.map_err(Error::Download)?;
 
 		// upload the map to the strafesnet group
 		let upload_response=self.cookie_context.create(rbx_asset::cookie::CreateRequest{
diff --git a/validation/src/validator.rs b/validation/src/validator.rs
index 1a980e9..1215ee4 100644
--- a/validation/src/validator.rs
+++ b/validation/src/validator.rs
@@ -1,6 +1,7 @@
 use futures::TryStreamExt;
 use submissions_api::types::ResourceType;
 
+use crate::download::download_asset_version;
 use crate::rbx_util::{class_is_a,read_dom,ReadDomError};
 use crate::types::ResourceID;
 
@@ -36,9 +37,7 @@ pub enum Error{
 	ScriptFlaggedIllegalKeyword(String),
 	ScriptBlocked(Option<submissions_api::types::ScriptID>),
 	ScriptNotYetReviewed(Option<submissions_api::types::ScriptID>),
-	ModelLocationDownload(rbx_asset::cloud::GetError),
-	NonFreeModel,
-	ModelFileDownload(rbx_asset::cloud::GetError),
+	Download(crate::download::Error),
 	ModelFileDecode(ReadDomError),
 	ApiGetScriptPolicyFromHash(submissions_api::types::SingleItemError),
 	ApiGetScript(submissions_api::Error),
@@ -91,19 +90,11 @@ impl From<crate::nats_types::ValidateSubmissionRequest> for ValidateRequest{
 
 impl crate::message_handler::MessageHandler{
 	pub async fn validate_inner(&self,validate_info:ValidateRequest)->Result<(),Error>{
-		// download the location of the map model
-		let location=self.cloud_context.get_asset_version_location(rbx_asset::cloud::GetAssetVersionRequest{
+		// download the map model
+		let model_data=download_asset_version(&self.cloud_context,rbx_asset::cloud::GetAssetVersionRequest{
 			asset_id:validate_info.ModelID,
 			version:validate_info.ModelVersion,
-		}).await.map_err(Error::ModelLocationDownload)?;
-
-		// if the location does not exist, you are not allowed to donwload it
-		let Some(location)=location.location else{
-			return Err(Error::NonFreeModel);
-		};
-
-		// download the map model
-		let model_data=self.cloud_context.get_asset(&location).await.map_err(Error::ModelFileDownload)?;
+		}).await.map_err(Error::Download)?;
 
 		// decode dom (slow!)
 		let mut dom=read_dom(std::io::Cursor::new(model_data)).map_err(Error::ModelFileDecode)?;