diff --git a/Cargo.lock b/Cargo.lock
index b5c381a..978e0ae 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -111,7 +111,7 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
 
 [[package]]
 name = "asset-tool"
-version = "0.4.10"
+version = "0.4.11"
 dependencies = [
  "anyhow",
  "clap",
@@ -1293,7 +1293,7 @@ dependencies = [
 
 [[package]]
 name = "rbx_asset"
-version = "0.3.3"
+version = "0.3.4"
 dependencies = [
  "chrono",
  "flate2",
diff --git a/Cargo.toml b/Cargo.toml
index 81b026b..f7dec71 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 workspace = { members = ["rbx_asset", "rox_compiler"] }
 [package]
 name = "asset-tool"
-version = "0.4.10"
+version = "0.4.11"
 edition = "2021"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
diff --git a/rbx_asset/Cargo.toml b/rbx_asset/Cargo.toml
index e457342..42ee64b 100644
--- a/rbx_asset/Cargo.toml
+++ b/rbx_asset/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "rbx_asset"
-version = "0.3.3"
+version = "0.3.4"
 edition = "2021"
 publish = ["strafesnet"]
 repository = "https://git.itzana.me/StrafesNET/asset-tool"
diff --git a/rbx_asset/src/cookie.rs b/rbx_asset/src/cookie.rs
index 00b22ed..f09223d 100644
--- a/rbx_asset/src/cookie.rs
+++ b/rbx_asset/src/cookie.rs
@@ -31,6 +31,8 @@ pub enum CreateError{
 		response:String,
 		err:std::num::ParseIntError,
 	},
+	VersionHeaderMissing,
+	ToStr(reqwest::header::ToStrError),
 }
 impl std::fmt::Display for CreateError{
 	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -59,6 +61,8 @@ pub enum UploadError{
 		response:String,
 		err:std::num::ParseIntError,
 	},
+	VersionHeaderMissing,
+	ToStr(reqwest::header::ToStrError),
 }
 impl std::fmt::Display for UploadError{
 	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -70,6 +74,7 @@ impl std::error::Error for UploadError{}
 #[allow(nonstandard_style,dead_code)]
 pub struct UploadResponse{
 	pub AssetId:u64,
+	pub AssetVersion:u64,
 }
 
 #[allow(nonstandard_style,dead_code)]
@@ -387,12 +392,23 @@ impl CookieContext{
 		}
 		let response=crate::response_ok(
 			self.post(url,body).await.map_err(CreateError::PostError)?
-		).await.map_err(CreateError::Response)?
-		.text().await.map_err(CreateError::Reqwest)?;
+		).await.map_err(CreateError::Response)?;
+
+		let version_str=response
+			.headers()
+			.get("roblox-assetversionnumber")
+			.ok_or(CreateError::VersionHeaderMissing)?
+			.to_str()
+			.map_err(CreateError::ToStr)?;
+		let version=version_str.parse()
+			.map_err(|err|CreateError::ParseInt{err,response:version_str.to_owned()})?;
+
+		let response=response.text().await.map_err(CreateError::Reqwest)?;
 
 		match response.parse(){
 			Ok(asset_id)=>Ok(UploadResponse{
 				AssetId:asset_id,
+				AssetVersion:version,
 			}),
 			Err(err)=>Err(CreateError::ParseInt{
 				response,
@@ -428,12 +444,23 @@ impl CookieContext{
 		}
 		let response=crate::response_ok(
 			self.post(url,body).await.map_err(UploadError::PostError)?
-		).await.map_err(UploadError::Response)?
-		.text().await.map_err(UploadError::Reqwest)?;
+		).await.map_err(UploadError::Response)?;
+
+		let version_str=response
+			.headers()
+			.get("roblox-assetversionnumber")
+			.ok_or(UploadError::VersionHeaderMissing)?
+			.to_str()
+			.map_err(UploadError::ToStr)?;
+		let version=version_str.parse()
+			.map_err(|err|UploadError::ParseInt{err,response:version_str.to_owned()})?;
+
+		let response=response.text().await.map_err(UploadError::Reqwest)?;
 
 		match response.parse(){
 			Ok(asset_id)=>Ok(UploadResponse{
 				AssetId:asset_id,
+				AssetVersion:version,
 			}),
 			Err(err)=>Err(UploadError::ParseInt{
 				response,
diff --git a/src/main.rs b/src/main.rs
index e8501ba..9d4c79b 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -133,6 +133,8 @@ struct DownloadUserInventoryJsonSubcommand{
 	output_folder:Option<PathBuf>,
 	#[arg(long)]
 	user_id:u64,
+	#[arg(long)]
+	continue_from_cursor:Option<bool>,
 }
 /// Upload a (.rbxm, .rbxmx) model file, creating a new asset.  Can be any type of model, including modulescripts.
 #[derive(Args)]
@@ -539,6 +541,7 @@ async fn main()->AResult<()>{
 			).await?,
 			subcommand.user_id,
 			subcommand.output_folder.unwrap_or_else(||std::env::current_dir().unwrap()),
+			subcommand.continue_from_cursor.unwrap_or(false),
 		).await,
 		Commands::CreateAsset(subcommand)=>create_asset(CreateAssetConfig{
 			cookie:cookie_from_args(
@@ -1058,30 +1061,70 @@ async fn download_creations_json(cookie:Cookie,owner:rbx_asset::cookie::Owner,ou
 	Ok(())
 }
 
-async fn get_user_inventory_pages(context:&CookieContext,user_id:u64)->AResult<Vec<rbx_asset::cookie::UserInventoryItem>>{
-	let mut config=rbx_asset::cookie::UserInventoryPageRequest{
-		user_id,
-		cursor:None,
-	};
-	let mut asset_list=Vec::new();
+async fn get_user_inventory_pages(
+	context:&CookieContext,
+	asset_list:&mut Vec<rbx_asset::cookie::UserInventoryItem>,
+	config:&mut rbx_asset::cookie::UserInventoryPageRequest,
+)->AResult<()>{
 	loop{
-		let mut page=context.get_user_inventory_page(&config).await?;
-		asset_list.append(&mut page.data);
-		if page.nextPageCursor.is_none(){
+		let page=context.get_user_inventory_page(&config).await?;
+		asset_list.extend(page.data);
+		config.cursor=page.nextPageCursor;
+		if config.cursor.is_none(){
 			break;
 		}
-		config.cursor=page.nextPageCursor;
 	}
-	Ok(asset_list)
+	Ok(())
 }
 
-async fn download_user_inventory_json(cookie:Cookie,user_id:u64,output_folder:PathBuf)->AResult<()>{
-	let context=CookieContext::new(cookie);
-	let item_list=get_user_inventory_pages(&context,user_id).await?;
+async fn download_user_inventory_json(cookie:Cookie,user_id:u64,output_folder:PathBuf,continue_from_cursor:bool)->AResult<()>{
+	let mut versions_path=output_folder.clone();
+	versions_path.set_file_name("versions.json");
+	let mut cursor_path=output_folder.clone();
+	cursor_path.set_file_name("cursor.json");
 
-	let mut path=output_folder.clone();
-	path.set_file_name("versions.json");
-	tokio::fs::write(path,serde_json::to_string(&item_list)?).await?;
+	let context=CookieContext::new(cookie);
+
+	let (mut asset_list,mut config)=if continue_from_cursor{
+		// load state from files
+		let (versions,cursor)=tokio::try_join!(
+			tokio::fs::read(versions_path.as_path()),
+			tokio::fs::read_to_string(cursor_path.as_path()),
+		)?;
+		(
+			serde_json::from_slice(&versions)?,
+			rbx_asset::cookie::UserInventoryPageRequest{
+				user_id,
+				cursor:Some(cursor),
+			}
+		)
+	}else{
+		// create new state
+		(
+			Vec::new(),
+			rbx_asset::cookie::UserInventoryPageRequest{
+				user_id,
+				cursor:None,
+			}
+		)
+	};
+
+	match get_user_inventory_pages(&context,&mut asset_list,&mut config).await{
+		Ok(())=>println!("Pages polling complete"),
+		Err(e)=>println!("Error: {e}"),
+	}
+
+	let cursor_fut=async{
+		if let Some(cursor)=config.cursor{
+			println!("writing cursor state...");
+			// there was a problem, write out cursor
+			tokio::fs::write(cursor_path,cursor).await?;
+		}
+		Ok(())
+	};
+	let versions_fut=tokio::fs::write(versions_path,serde_json::to_string(&asset_list)?);
+
+	tokio::try_join!(versions_fut,cursor_fut)?;
 
 	Ok(())
 }