2 unstable releases
Uses new Rust 2024
| 0.2.0 | Oct 30, 2025 |
|---|---|
| 0.1.0 | Oct 28, 2025 |
#731 in Asynchronous
51KB
900 lines
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
tokioandreqwestfor 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")?;
// Fetch up to 50 listings priced between $1.00 and $10.00 (i.e., 100–1000 cents)
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, // 5000 cents = $50.00
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; // 5000 cents = $50.00
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")?;
// Get the complete schema with weapon pricing data
let schema = client.get_schema().await?;
println!("Total weapons: {}", schema.weapons.len());
// Find AK-47 Redline pricing
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:");
// Normal prices by wear condition
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);
}
}
}
// StatTrak prices if available
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);
}
}
}
}
}
// Find most expensive skins
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 { // Over $1000
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 { // Fetch 5 pages
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; // No more pages
}
}
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:
// HTTP proxy
let client = Client::with_proxy("API_KEY", "http://proxy:8080")?;
// SOCKS5 proxy with auth
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:
- Apache License, Version 2.0 (LICENSE-APACHE or Apache 2.0)
- MIT License (LICENSE-MIT or MIT)
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.
Dependencies
~6–22MB
~235K SLoC