CSFloat Async API Client (Unofficial)

An unofficial, asynchronous Rust library for interacting with the CSFloat API. This library provides full support for programmatic access to listings, buy orders, user data, exchange rates, and more. All prices returned by the server are in cents.
Key Features
- Asynchronous design: Built on
tokio and reqwest for non-blocking I/O.
- Type-safe: Fully typed models using Rust's type system and
serde.
- Fetch listings: Retrieve detailed listings with filters (price in cents, float, rarity, etc.).
- Buy orders: Get and manage buy orders for specific items.
- User information: Access your own profile, trades, and stall data.
- Weapon pricing schema: Get average prices for all weapon skins across different wear conditions.
- Listing management: Create, delete, and modify listings and buy orders.
- Proxy support: Optional SOCKS4/5 and HTTP(S) proxy support.
- Error handling: Clear error types with descriptive messages.
- Builder pattern: Ergonomic API for complex queries.
Installation
Add this to your Cargo.toml:
[dependencies]
csfloat-rs = "0.1"
tokio = { version = "1.0", features = ["full"] }
Quick Start
use csfloat_rs::{Client, Result};
#[tokio::main]
async fn main() -> Result<()> {
let client = Client::new("YOUR_API_KEY")?;
let response = client
.get_all_listings()
.min_price(100)
.max_price(1000)
.limit(50)
.send()
.await?;
for listing in response.listings() {
println!(
"ID: {}, Price: {} cents, Float: {:?}",
listing.id,
listing.price,
listing.item.float_value
);
}
Ok(())
}
Examples
Create a Buy Order
use csfloat_rs::{Client, client::CreateBuyOrderRequest};
#[tokio::main]
async fn main() -> Result<()> {
let client = Client::new("YOUR_API_KEY")?;
let request = CreateBuyOrderRequest {
market_hash_name: "AK-47 | Redline (Field-Tested)".to_string(),
max_price: 5000, quantity: 1,
};
let buy_order = client.create_buy_order(request).await?;
println!("Buy order created: {:?}", buy_order);
Ok(())
}
Get User Profile
use csfloat_rs::Client;
#[tokio::main]
async fn main() -> Result<()> {
let client = Client::new("YOUR_API_KEY")?;
let me = client.get_me().await?;
println!("Username: {:?}", me.user.username);
println!("Balance: {:?} cents", me.user.balance);
println!("Total trades: {:?}", me.user.statistics.map(|s| s.total_trades));
Ok(())
}
Advanced Listing Search
use csfloat_rs::{Client, client::{SortBy, Category}};
#[tokio::main]
async fn main() -> Result<()> {
let client = Client::new("YOUR_API_KEY")?;
let response = client
.get_all_listings()
.min_price(1000)
.max_price(50000)
.min_float(0.0)
.max_float(0.15)
.sort_by(SortBy::LowestFloat)
.category(Category::StatTrak)
.market_hash_name("AWP | Asiimov (Field-Tested)".to_string())
.limit(20)
.send()
.await?;
for listing in response.listings() {
if let Some(float) = listing.item.float_value {
println!("Listing {}: Float {:.8}", listing.id, float);
}
}
Ok(())
}
Using Proxy
use csfloat_rs::Client;
#[tokio::main]
async fn main() -> Result<()> {
let client = Client::with_proxy(
"YOUR_API_KEY",
"socks5://user:pass@host:port"
)?;
let listings = client
.get_all_listings()
.limit(10)
.send()
.await?;
println!("Found {} listings via proxy", listings.data.len());
Ok(())
}
Buy an Item
use csfloat_rs::Client;
#[tokio::main]
async fn main() -> Result<()> {
let client = Client::new("YOUR_API_KEY")?;
let listing_id = 123456789;
let total_price = 5000;
let result = client.buy_now(total_price, listing_id).await?;
println!("Purchase result: {:?}", result);
Ok(())
}
Get Weapon Pricing Schema
use csfloat_rs::{Client, models::WearCondition};
#[tokio::main]
async fn main() -> Result<()> {
let client = Client::new("YOUR_API_KEY")?;
let schema = client.get_schema().await?;
println!("Total weapons: {}", schema.weapons.len());
if let Some((_, ak47)) = schema.get_weapon_by_name("AK-47") {
if let Some(redline) = ak47.get_paint_by_name("Redline") {
println!("AK-47 Redline prices:");
for wear in [WearCondition::FactoryNew, WearCondition::MinimalWear,
WearCondition::FieldTested, WearCondition::WellWorn,
WearCondition::BattleScarred] {
if let Some(price) = redline.price_for_wear(wear) {
if let Some(volume) = redline.volume_for_wear(wear) {
println!(" {} - ${:.2} (Volume: {})",
wear.as_str(), price as f64 / 100.0, volume);
}
}
}
if redline.has_stattrak() {
println!("StatTrak prices:");
for wear in [WearCondition::MinimalWear, WearCondition::FieldTested] {
if let Some(price) = redline.stattrak_price_for_wear(wear) {
println!(" StatTrak {} - ${:.2}",
wear.as_str(), price as f64 / 100.0);
}
}
}
}
}
let mut expensive_skins: Vec<(&str, &str, u64)> = Vec::new();
for (_, weapon) in &schema.weapons {
for paint in weapon.paints.values() {
if let Some(price) = paint.price_for_wear(WearCondition::FactoryNew) {
if price > 100000 { expensive_skins.push((&weapon.name, &paint.name, price));
}
}
}
}
expensive_skins.sort_by(|a, b| b.2.cmp(&a.2));
println!("Most expensive Factory New skins:");
for (weapon, skin, price) in expensive_skins.iter().take(5) {
println!(" {} | {} - ${:.2}", weapon, skin, *price as f64 / 100.0);
}
Ok(())
}
Pagination
use csfloat_rs::Client;
#[tokio::main]
async fn main() -> Result<()> {
let client = Client::new("YOUR_API_KEY")?;
let mut cursor: Option<String> = None;
let mut all_listings = Vec::new();
for _ in 0..5 { let mut builder = client.get_all_listings().limit(50);
if let Some(c) = cursor {
builder = builder.cursor(c);
}
let response = builder.send().await?;
all_listings.extend(response.data);
cursor = response.cursor;
if cursor.is_none() {
break; }
}
println!("Fetched {} total listings", all_listings.len());
Ok(())
}
Core Methods
Market Data
get_exchange_rates() – Retrieve current exchange rates.
get_schema() – Get weapon pricing schema with average prices (undocumented endpoint).
get_all_listings() – List items with optional filters (returns builder).
get_specific_listing(listing_id) – Get detailed info for a specific listing.
get_similar(listing_id) – Get similar listings.
get_sales(market_hash_name, paint_index) – Get sales history.
Buy Orders
get_buy_orders(listing_id, limit) – Retrieve buy orders for a listing.
get_my_buy_orders(page, limit) – List your own buy orders.
create_buy_order(request) – Place a buy order.
delete_buy_order(id) – Cancel an existing buy order.
User Data
get_me() – Fetch authenticated user profile.
get_stall(user_id, limit) – Get a user's stall (listed items).
get_inventory() – Get your inventory.
get_watchlist(limit) – Get your watchlist.
get_transactions(page, limit) – Get transaction history.
get_trade_history(role, limit, page) – Get trade history.
Listing Management
create_listing(request) – Create a new listing.
delete_listing(listing_id) – Delete a listing.
update_listing_price(listing_id, price) – Update listing price.
make_offer(listing_id, price) – Make an offer on a listing.
buy_now(total_price, listing_id) – Instantly buy a listing.
Error Handling
The client uses a custom Result type and provides detailed error information:
use csfloat_rs::{Client, Error};
#[tokio::main]
async fn main() {
let client = Client::new("YOUR_API_KEY").unwrap();
match client.get_specific_listing(123456).await {
Ok(listing) => println!("Found listing: {:?}", listing),
Err(Error::NotFound) => println!("Listing not found"),
Err(Error::Unauthorized) => println!("Invalid API key"),
Err(Error::TooManyRequests) => println!("Rate limited, slow down!"),
Err(e) => println!("Other error: {}", e),
}
}
Proxy Support
Support for HTTP, HTTPS, SOCKS4, and SOCKS5 proxies:
let client = Client::with_proxy("API_KEY", "http://proxy:8080")?;
let client = Client::with_proxy("API_KEY", "socks5://user:pass@proxy:1080")?;
Contributing
Contributions are welcome! Feel free to submit a Pull Request.
License
This project is licensed under either of:
at your option.
Disclaimer
This is an unofficial library and is not affiliated with or endorsed by CSFloat. Use at your own risk and ensure compliance with CSFloat's Terms of Service.