A comprehensive TypeScript library for encoding and decoding Counter-Strike 2 inspect URLs with full protobuf support, Steam client integration, validation, and error handling.
CEconItemPreviewDataBlock
messagedecodeMaskedData()
for fastest possible decodinghighlight_reel
, style
, variations
, upgrade_level
entindex
npm install cs2-inspect-lib
For global CLI usage:
npm install -g cs2-inspect-lib
import {
// Fastest - Static methods (no instance creation)
decodeMaskedData,
analyzeUrl,
requiresSteamClient,
// Fast - Convenience functions
createInspectUrl,
inspectItem,
// Standard - Instance methods
CS2Inspect,
WeaponType,
WeaponPaint,
ItemRarity
} from 'cs2-inspect-lib';
// FASTEST - Direct hex data decoding
const hexData = "001807A8B4C5D6E7F8..."; // Raw protobuf hex
const item = decodeMaskedData(hexData); // Instant decoding
// FAST - Static URL analysis (no instance needed)
const analyzed = analyzeUrl(url);
console.log(analyzed.url_type); // 'masked' or 'unmasked'
console.log(analyzed.hex_data); // Hex data if available
// Quick Steam client requirement check
const needsSteam = requiresSteamClient(url);
import { CS2Inspect, WeaponType, WeaponPaint, ItemRarity } from 'cs2-inspect-lib';
const cs2 = new CS2Inspect();
// Create an inspect URL
const item = {
defindex: WeaponType.AK_47,
paintindex: WeaponPaint.AK_47_FIRE_SERPENT, // Clear weapon + skin naming
paintseed: 661,
paintwear: 0.15,
rarity: ItemRarity.COVERT,
stickers: [
{
slot: 0,
sticker_id: 1,
wear: 0.1,
highlight_reel: 1
}
],
style: 5,
upgrade_level: 3
};
const url = cs2.createInspectUrl(item);
console.log(url);
// Universal inspection (works with any URL type)
const decoded = await cs2.inspectItem(url);
console.log(decoded);
import {
createInspectUrl,
inspectItem,
decodeMaskedUrl,
analyzeUrl
} from 'cs2-inspect-lib';
// Create URL
const url = createInspectUrl(item);
// Universal inspection (auto-detects URL type)
const decoded = await inspectItem(url);
// Fast masked-only decoding
const maskedItem = decodeMaskedUrl(maskedUrl);
// Quick URL analysis
const analysis = analyzeUrl(url);
import { CS2Inspect, validateItem } from 'cs2-inspect-lib';
// Validate an item before encoding
const validation = validateItem(item);
if (!validation.valid) {
console.error('Validation errors:', validation.errors);
if (validation.warnings) {
console.warn('Warnings:', validation.warnings);
}
}
// Configure validation settings
const cs2 = new CS2Inspect({
validateInput: true,
maxCustomNameLength: 50,
enableLogging: true
});
The complete API documentation is available online, including:
import {
decodeMaskedData,
analyzeUrl,
requiresSteamClient,
isValidUrl,
normalizeUrl,
validateUrl,
validateItem
} from 'cs2-inspect-lib';
// Direct protobuf decoding - FASTEST possible method
decodeMaskedData(hexData: string, config?: CS2InspectConfig): EconItem
// URL analysis without instance creation
analyzeUrl(url: string, config?: CS2InspectConfig): AnalyzedInspectURL
requiresSteamClient(url: string, config?: CS2InspectConfig): boolean
isValidUrl(url: string, config?: CS2InspectConfig): boolean
normalizeUrl(url: string, config?: CS2InspectConfig): string
// Validation without instance creation
validateUrl(url: string): ValidationResult
validateItem(item: any): ValidationResult
import {
createInspectUrl,
inspectItem,
decodeMaskedUrl
} from 'cs2-inspect-lib';
// Universal functions with automatic Steam client handling
createInspectUrl(item: EconItem, config?: CS2InspectConfig): string
inspectItem(url: string, config?: CS2InspectConfig): Promise<EconItem | SteamInspectResult>
decodeMaskedUrl(url: string, config?: CS2InspectConfig): EconItem
CS2Inspect
Main API class for encoding and decoding inspect URLs.
const cs2 = new CS2Inspect(config?: CS2InspectConfig);
// Core Methods
cs2.createInspectUrl(item: EconItem): string
cs2.decodeMaskedUrl(url: string): EconItem // NEW: Clear naming
cs2.inspectItem(url: string): Promise<EconItem | SteamInspectResult> // NEW: Universal method
cs2.analyzeUrl(url: string): AnalyzedInspectURL
cs2.validateItem(item: any): ValidationResult
cs2.validateUrl(url: string): ValidationResult
cs2.normalizeUrl(url: string): string
// Deprecated (still work, but use new methods above)
cs2.decodeInspectUrl(url: string): EconItem // Use decodeMaskedUrl()
cs2.decodeInspectUrlAsync(url: string): Promise<EconItem | SteamInspectResult> // Use inspectItem()
cs2.isValidUrl(url: string): boolean // Use analyzeUrl() + try/catch
// Steam Client Methods
cs2.initializeSteamClient(): Promise<void>
cs2.isSteamClientReady(): boolean
cs2.getSteamClientStats(): SteamClientStats
cs2.requiresSteamClient(url: string): boolean
cs2.connectToServer(serverAddress: string): Promise<void>
cs2.disconnectSteamClient(): Promise<void>
// Configuration
cs2.updateConfig(newConfig: Partial<CS2InspectConfig>): void
cs2.getConfig(): Required<CS2InspectConfig>
decodeMaskedData()
when:import { decodeMaskedData } from 'cs2-inspect-lib';
const item = decodeMaskedData('001807A8B4C5D6E7F8...');
import { analyzeUrl, requiresSteamClient } from 'cs2-inspect-lib';
const analysis = analyzeUrl(url);
const needsSteam = requiresSteamClient(url);
inspectItem()
when:import { inspectItem } from 'cs2-inspect-lib';
const item = await inspectItem(anyUrl); // Works with masked or unmasked
const cs2 = new CS2Inspect({ enableLogging: true });
await cs2.initializeSteamClient();
const item = await cs2.inspectItem(url);
WeaponPaint
Comprehensive enum with 1800+ weapon paint indices generated from CS2 skins database:
enum WeaponPaint {
VANILLA = 0,
// AK-47 Skins (weapon-specific naming)
AK_47_FIRE_SERPENT = 180,
AK_47_REDLINE = 282,
AK_47_VULCAN = 300,
AK_47_CASE_HARDENED = 44,
AK_47_WASTELAND_REBEL = 380,
// AWP Skins
AWP_DRAGON_LORE = 344,
AWP_MEDUSA = 425,
AWP_LIGHTNING_STRIKE = 179,
AWP_ASIIMOV = 279,
AWP_HYPER_BEAST = 446,
// M4A4 Skins
M4A4_HOWL = 309,
M4A4_ASIIMOV = 255,
M4A4_DRAGON_KING = 360,
M4A4_DESOLATE_SPACE = 584,
// Knife Skins (weapon-specific variants)
KARAMBIT_DOPPLER = 417,
KARAMBIT_MARBLE_FADE = 413,
KARAMBIT_TIGER_TOOTH = 409,
BAYONET_DOPPLER = 417,
BAYONET_MARBLE_FADE = 413,
// Glove Skins
SPORT_GLOVES_PANDORAS_BOX = 10037,
SPECIALIST_GLOVES_CRIMSON_KIMONO = 10033,
// ... 1800+ total paint definitions covering all CS2 skins
}
Utility Functions:
// Get paint name from index
getPaintName(paintIndex: number): string | undefined
// Get paint index from name
getPaintIndex(paintName: string): number | undefined
// Type guard
isWeaponPaint(value: any): value is WeaponPaint
// Get all available paints
getAllPaintNames(): string[]
getAllPaintIndices(): number[]
EconItem
Complete item data structure matching CS2's CEconItemPreviewDataBlock
:
interface EconItem {
// Required fields
defindex: number | WeaponType;
paintindex: number | WeaponPaint;
paintseed: number;
paintwear: number;
// Optional fields
accountid?: number;
itemid?: number | bigint;
rarity?: ItemRarity | number;
quality?: number;
killeaterscoretype?: number;
killeatervalue?: number;
customname?: string;
inventory?: number;
origin?: number;
questid?: number;
dropreason?: number;
musicindex?: number;
entindex?: number;
petindex?: number;
// Array fields
stickers?: Sticker[];
keychains?: Sticker[];
variations?: Sticker[];
// CS2 specific fields
style?: number;
upgrade_level?: number;
}
Sticker
Sticker/keychain/variation data structure:
interface Sticker {
slot: number;
sticker_id: number;
wear?: number;
scale?: number;
rotation?: number;
tint_id?: number;
offset_x?: number;
offset_y?: number;
offset_z?: number;
pattern?: number;
highlight_reel?: number;
}
interface CS2InspectConfig {
validateInput?: boolean; // Default: true
maxUrlLength?: number; // Default: 2048
maxCustomNameLength?: number; // Default: 100
enableLogging?: boolean; // Default: false
steamClient?: SteamClientConfig;
}
interface SteamClientConfig {
enabled?: boolean; // Default: false
username?: string;
password?: string;
apiKey?: string; // Optional
rateLimitDelay?: number; // Default: 1500ms
maxQueueSize?: number; // Default: 100
requestTimeout?: number; // Default: 10000ms
queueTimeout?: number; // Default: 30000ms
serverAddress?: string; // Optional
}
The library provides comprehensive error handling with custom error types:
import {
CS2InspectError,
ValidationError,
EncodingError,
DecodingError,
SteamConnectionError,
SteamAuthenticationError,
SteamTimeoutError,
SteamQueueFullError,
SteamNotReadyError,
SteamInspectionError
} from 'cs2-inspect-lib';
try {
const url = cs2.createInspectUrl(item);
} catch (error) {
if (error instanceof ValidationError) {
console.error('Validation failed:', error.message);
console.error('Context:', error.context);
} else if (error instanceof EncodingError) {
console.error('Encoding failed:', error.message);
}
}
The library includes a powerful command-line tool:
# Decode a masked inspect URL (protobuf data)
cs2inspect decode "steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20..."
# Decode an unmasked URL (requires Steam credentials)
cs2inspect decode "steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20S76561198123456789A987654321D456789123" \
--enable-steam --steam-username your_username --steam-password your_password
# Create an inspect URL
cs2inspect encode --weapon AK_47 --paint 44 --seed 661 --float 0.15
# Validate an inspect URL
cs2inspect validate "steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20..."
# Get URL information
cs2inspect info "steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20..."
For complete CLI documentation, run:
cs2inspect --help
The library supports two types of inspect URLs with optimized detection:
import { analyzeUrl, requiresSteamClient } from 'cs2-inspect-lib';
// Fast static analysis - no instance creation
const analysis = analyzeUrl(url);
console.log(analysis.url_type); // 'masked' or 'unmasked'
// Quick Steam client requirement check
const needsSteam = requiresSteamClient(url); // Optimized static method
These contain encoded item data and can be decoded instantly offline:
steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20001807A8...
import { decodeMaskedData, decodeMaskedUrl } from 'cs2-inspect-lib';
// FASTEST - Direct hex data decoding
const item1 = decodeMaskedData('001807A8B4C5D6E7F8...');
// Fast - URL parsing + decoding
const item2 = decodeMaskedUrl(maskedUrl);
These reference items in Steam's database and require Steam client authentication:
Market Listing:
steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20M123456789A987654321D456789123
Inventory Item:
steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20S76561198123456789A987654321D456789123
import { inspectItem } from 'cs2-inspect-lib';
// Works with ANY URL type - automatically detects and handles
const item = await inspectItem(anyUrl); // Masked or unmasked
import { CS2Inspect } from 'cs2-inspect-lib';
// Configure with Steam client support
const cs2 = new CS2Inspect({
steamClient: {
enabled: true,
username: 'your_steam_username',
password: 'your_steam_password',
rateLimitDelay: 1500, // ms between requests
maxQueueSize: 100,
requestTimeout: 30000, // 30 second timeout
enableLogging: false
}
});
// Initialize Steam client
await cs2.initializeSteamClient();
// Universal inspection - works with any URL type
const item = await cs2.inspectItem(anyUrl);
// Get Steam client status
const stats = cs2.getSteamClientStats();
console.log('Steam client status:', stats.status);
console.log('Queue length:', stats.queueLength);
For security, you can use environment variables instead of hardcoding credentials:
export STEAM_USERNAME=your_username
export STEAM_PASSWORD=your_password
const cs2 = new CS2Inspect({
steamClient: {
enabled: true,
username: process.env.STEAM_USERNAME,
password: process.env.STEAM_PASSWORD
}
});
import { decodeMaskedData } from 'cs2-inspect-lib';
// FASTEST - Direct protobuf decoding from hex data
const hexData = "001807A8B4C5D6E7F8..."; // Raw protobuf hex
const item = decodeMaskedData(hexData); // Instant decoding, zero overhead
console.log(`Weapon: ${item.defindex}, Paint: ${item.paintindex}`);
import { analyzeUrl, requiresSteamClient, isValidUrl } from 'cs2-inspect-lib';
// Fast URL analysis without instance creation
const analysis = analyzeUrl(url);
console.log(`URL Type: ${analysis.url_type}`); // 'masked' or 'unmasked'
console.log(`Has Hex Data: ${!!analysis.hex_data}`);
// Quick checks
const needsSteam = requiresSteamClient(url); // Fast static check
const isValid = isValidUrl(url); // Fast validation
import { inspectItem, createInspectUrl } from 'cs2-inspect-lib';
// Create URL
const item = {
defindex: WeaponType.AK_47,
paintindex: WeaponPaint.AK_47_FIRE_SERPENT,
paintseed: 661,
paintwear: 0.15,
rarity: ItemRarity.COVERT
};
const url = createInspectUrl(item);
// Universal inspection - works with any URL type
const decoded = await inspectItem(url); // Auto-detects masked/unmasked
console.log(decoded);
import { CS2Inspect, WeaponType, WeaponPaint, ItemRarity, getPaintName } from 'cs2-inspect-lib';
const cs2 = new CS2Inspect();
// Create items using comprehensive WeaponPaint enum with clear weapon + skin naming
const akFireSerpent = {
defindex: WeaponType.AK_47,
paintindex: WeaponPaint.AK_47_FIRE_SERPENT, // Much clearer than using 180
paintseed: 661,
paintwear: 0.15,
rarity: ItemRarity.COVERT
};
const awpDragonLore = {
defindex: WeaponType.AWP,
paintindex: WeaponPaint.AWP_DRAGON_LORE, // Much clearer than using 344
paintseed: 420,
paintwear: 0.07,
rarity: ItemRarity.COVERT
};
// Create inspect URLs
const akUrl = cs2.createInspectUrl(akFireSerpent);
const awpUrl = cs2.createInspectUrl(awpDragonLore);
// Fast masked URL decoding
const decoded = cs2.decodeMaskedUrl(akUrl); // New clear method name
console.log(`Paint: ${getPaintName(decoded.paintindex as number)}`);
```### Complete Item with All Fields
```typescript
const complexItem: EconItem = {
accountid: 123456789,
itemid: BigInt('9876543210'),
defindex: WeaponType.AWP,
paintindex: WeaponPaint.AWP_DRAGON_LORE, // Clear weapon + skin naming
rarity: ItemRarity.COVERT,
quality: 4,
paintwear: 0.15,
paintseed: 420,
killeaterscoretype: 1,
killeatervalue: 1337,
customname: 'Dragon Lore',
stickers: [
{
slot: 0,
sticker_id: 5032,
wear: 0.15,
scale: 1.2,
rotation: 45.0,
tint_id: 1,
offset_x: 0.1,
offset_y: -0.1,
offset_z: 0.05,
pattern: 10,
highlight_reel: 1
}
],
keychains: [
{
slot: 0,
sticker_id: 20,
pattern: 148,
highlight_reel: 2
}
],
style: 7,
variations: [
{
slot: 0,
sticker_id: 100,
pattern: 50,
highlight_reel: 3
}
],
upgrade_level: 10,
entindex: -1
};
const url = createInspectUrl(complexItem);
const decoded = decodeInspectUrl(url);
import { CS2Inspect, ValidationError, DecodingError } from 'cs2-inspect-lib';
const cs2 = new CS2Inspect({ validateInput: true });
try {
const item = {
defindex: -1, // Invalid
paintindex: 44,
paintseed: 661,
paintwear: 1.5 // Invalid
};
const url = cs2.createInspectUrl(item);
} catch (error) {
if (error instanceof ValidationError) {
console.error('Validation errors:');
error.context?.errors?.forEach(err => console.error(` - ${err}`));
if (error.context?.warnings) {
console.warn('Warnings:');
error.context.warnings.forEach(warn => console.warn(` - ${warn}`));
}
}
}
The library includes comprehensive test examples:
# Run all tests
npm run example
# Run individual tests
npx ts-node examples/basic-usage.ts basic # Basic item creation
npx ts-node examples/basic-usage.ts complex # Complex items with stickers
npx ts-node examples/basic-usage.ts steam # Steam client integration
npx ts-node examples/basic-usage.ts debug "real_url_here" # Debug mode
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Run tests in watch mode
npm run test:watch
# Clone the repository
git clone https://github.com/sak0a/cs2-inspect-lib.git
cd cs2-inspect-lib
# Install dependencies
npm install
# Build the project
npm run build
# Generate documentation
npm run docs
# Run in development mode
npm run dev
# Lint code
npm run lint
npm run lint:fix
Contributions are welcome! Please read our contributing guidelines and submit pull requests to our repository.
git clone https://github.com/sak0a/cs2-inspect-lib.git
npm install
git checkout -b feature/your-feature-name
npm test
npm run build
Connection Timeouts:
# Enable debug mode to see where the process stops
npx ts-node examples/basic-usage.ts debug "your_real_url_here"
Authentication Failures:
Invalid URL Errors:
Enable comprehensive logging to troubleshoot issues:
const cs2 = new CS2Inspect({
enableLogging: true,
steamClient: {
enabled: true,
username: 'your_username',
password: 'your_password',
enableLogging: true, // Steam client debug logging
requestTimeout: 60000 // Extended timeout for debugging
}
});
The library now offers 3 performance tiers:
Operation | Old Method | New Method | Performance Gain |
---|---|---|---|
URL Analysis | new CS2Inspect().analyzeUrl() |
analyzeUrl() |
~90% faster |
Steam Check | new CS2Inspect().requiresSteamClient() |
requiresSteamClient() |
~85% faster |
Hex Decoding | new CS2Inspect().decodeInspectUrl() |
decodeMaskedData() |
~95% faster |
Validation | new CS2Inspect().isValidUrl() |
isValidUrl() |
~80% faster |
// OLD - Creates unnecessary instances
const cs2 = new CS2Inspect();
const analysis = cs2.analyzeUrl(url);
const needsSteam = cs2.requiresSteamClient(url);
const isValid = cs2.isValidUrl(url);
// NEW - Optimized static methods
import { analyzeUrl, requiresSteamClient, isValidUrl } from 'cs2-inspect-lib';
const analysis = analyzeUrl(url); // 90% faster
const needsSteam = requiresSteamClient(url); // 85% faster
const isValid = isValidUrl(url); // 80% faster
// OLD - Confusing method names
const item1 = cs2.decodeInspectUrl(url); // Only works with masked
const item2 = await cs2.decodeInspectUrlAsync(url); // Works with both
// NEW - Clear method names
const item1 = cs2.decodeMaskedUrl(url); // Clear: masked only
const item2 = await cs2.inspectItem(url); // Clear: universal method
decodeMaskedData()
for fastest possible decodingdecodeMaskedUrl()
and inspectItem()
for better clarityanalyzeUrl()
, requiresSteamClient()
, isValidUrl()
without instance creationAK_47_FIRE_SERPENT
, AWP_DRAGON_LORE
, KARAMBIT_DOPPLER
)EconItem.paintindex
to accept WeaponPaint | number
for full TypeScript supportgetPaintName()
, getPaintIndex()
, isWeaponPaint()
, getAllPaintNames()
, getAllPaintIndices()
MIT License - see LICENSE file for details.
If you encounter any issues or have questions: