token-costs 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,87 @@
1
+ # Token Prices
2
+
3
+ Daily-updated LLM pricing data for OpenAI, Anthropic, Google, and OpenRouter.
4
+
5
+ ## What Is This?
6
+
7
+ An npm package and JSON API that gives you up-to-date token pricing for major LLM providers. Stop hardcoding prices or manually checking pricing pages.
8
+
9
+ ```typescript
10
+ import { getModelPricing, calculateCost } from 'token-costs';
11
+
12
+ // Get pricing info for a model
13
+ const pricing = await getModelPricing('openai', 'gpt-4o');
14
+ // { input: 2.5, output: 10, context: 128000 }
15
+ ```
16
+
17
+ ```typescript
18
+ // Or calculate cost directly (fetches pricing automatically)
19
+ const cost = await calculateCost('anthropic', 'claude-sonnet-4', {
20
+ inputTokens: 1500,
21
+ outputTokens: 800,
22
+ });
23
+ // { totalCost: 0.0165, ... }
24
+ ```
25
+
26
+ Or fetch directly without dependencies:
27
+ ```javascript
28
+ const data = await fetch('https://mikkotikkanen.github.io/token-costs/api/v1/openai.json')
29
+ .then(r => r.json());
30
+ ```
31
+
32
+ ## Features
33
+
34
+ - **Daily updates** - Crawled automatically at 00:01 UTC
35
+ - **4 providers** - OpenAI, Anthropic, Google, OpenRouter
36
+ - **Zero dependencies** - npm package has no runtime dependencies
37
+ - **TypeScript** - Full type definitions included
38
+ - **Caching** - Fetches once per day, caches automatically
39
+ - **Stale detection** - Know when data might be outdated
40
+
41
+ ## Installation
42
+
43
+ ```bash
44
+ npm install token-costs
45
+ ```
46
+
47
+ ## Documentation
48
+
49
+ Full usage guide, API reference, and data formats: **[mikkotikkanen.github.io/token-costs](https://mikkotikkanen.github.io/token-costs)**
50
+
51
+ ## What's Included
52
+
53
+ ```
54
+ token-costs/
55
+ ├── PricingClient # Main client class with caching
56
+ ├── getModelPricing() # Quick lookup function
57
+ ├── calculateCost() # Cost calculation helper
58
+ └── TypeScript types # Full type definitions
59
+ ```
60
+
61
+ **API Endpoints** (JSON):
62
+ - `api/v1/openai.json`
63
+ - `api/v1/anthropic.json`
64
+ - `api/v1/google.json`
65
+ - `api/v1/openrouter.json`
66
+
67
+ ## Contributing
68
+
69
+ Found incorrect pricing? Want to add a provider? Contributions welcome!
70
+
71
+ ```bash
72
+ git clone https://github.com/mikkotikkanen/token-costs
73
+ cd token-costs
74
+ npm install
75
+ npm run build
76
+ npm test
77
+ ```
78
+
79
+ See [AGENTS.md](AGENTS.md) for development details.
80
+
81
+ ## For LLM Providers
82
+
83
+ We'd prefer not to scrape. Consider publishing `/llm_prices.json` on your website - a simple standard format that tools can fetch directly. See the [full proposal](https://mikkotikkanen.github.io/token-costs/#proposal) on the documentation site.
84
+
85
+ ## License
86
+
87
+ MIT
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Token Prices Client
3
+ * Fetches and caches provider pricing data with daily refresh
4
+ */
5
+ import type { Provider, ProviderFile, ModelPricing, PricingClientOptions, PriceLookupResult, CostResult } from './types.js';
6
+ /**
7
+ * Error thrown when a clock mismatch is detected
8
+ */
9
+ export declare class ClockMismatchError extends Error {
10
+ readonly clientDate: string;
11
+ readonly dataDate: string;
12
+ readonly daysDiff: number;
13
+ constructor(clientDate: string, dataDate: string, daysDiff: number);
14
+ }
15
+ /**
16
+ * Token Prices Client
17
+ *
18
+ * Provides access to LLM pricing data with automatic caching and daily refresh.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * import { PricingClient } from 'token-prices';
23
+ *
24
+ * const client = new PricingClient();
25
+ *
26
+ * // Get pricing for a model
27
+ * const pricing = await client.getModelPricing('openai', 'gpt-4o');
28
+ * console.log(pricing.input, pricing.output);
29
+ *
30
+ * // Calculate cost
31
+ * const cost = await client.calculateCost('anthropic', 'claude-sonnet-4', {
32
+ * inputTokens: 1000,
33
+ * outputTokens: 500,
34
+ * });
35
+ * console.log(cost.totalCost);
36
+ * ```
37
+ */
38
+ export declare class PricingClient {
39
+ private baseUrl;
40
+ private fetchFn;
41
+ private timeOffsetMs;
42
+ private cache;
43
+ private externalCache?;
44
+ constructor(options?: PricingClientOptions);
45
+ /**
46
+ * Get today's date according to this client (with offset applied)
47
+ */
48
+ private getToday;
49
+ /**
50
+ * Get cache key for external cache
51
+ */
52
+ private getCacheKey;
53
+ /**
54
+ * Try to load from external cache
55
+ */
56
+ private loadFromExternalCache;
57
+ /**
58
+ * Save to external cache
59
+ */
60
+ private saveToExternalCache;
61
+ /**
62
+ * Fetch provider data, using cache if available and fresh
63
+ */
64
+ private fetchProvider;
65
+ /**
66
+ * Get the effective pricing data, handling the dual-date fallback
67
+ */
68
+ private getEffectiveData;
69
+ /**
70
+ * Get pricing for a specific model
71
+ *
72
+ * @param provider - The provider (openai, anthropic, google, openrouter)
73
+ * @param modelId - The model identifier
74
+ * @returns The pricing data for the model
75
+ * @throws Error if model is not found
76
+ */
77
+ getModelPricing(provider: Provider, modelId: string): Promise<PriceLookupResult>;
78
+ /**
79
+ * Get pricing for a model, returning null if not found
80
+ */
81
+ getModelPricingOrNull(provider: Provider, modelId: string): Promise<PriceLookupResult | null>;
82
+ /**
83
+ * Get all models for a provider
84
+ */
85
+ getProviderModels(provider: Provider): Promise<Record<string, ModelPricing>>;
86
+ /**
87
+ * List all model IDs for a provider
88
+ */
89
+ listModels(provider: Provider): Promise<string[]>;
90
+ /**
91
+ * Calculate cost for a given number of tokens
92
+ *
93
+ * @param provider - The provider
94
+ * @param modelId - The model identifier
95
+ * @param tokens - Token counts
96
+ * @param tokens.inputTokens - Number of input tokens
97
+ * @param tokens.outputTokens - Number of output tokens
98
+ * @param tokens.cachedInputTokens - Number of cached input tokens (optional)
99
+ */
100
+ calculateCost(provider: Provider, modelId: string, tokens: {
101
+ inputTokens: number;
102
+ outputTokens: number;
103
+ cachedInputTokens?: number;
104
+ }): Promise<CostResult>;
105
+ /**
106
+ * Get the raw provider file (includes both current and previous data)
107
+ */
108
+ getRawProviderData(provider: Provider): Promise<ProviderFile>;
109
+ /**
110
+ * Get the date of the currently cached data for a provider
111
+ * Returns null if no data is cached
112
+ */
113
+ getCachedDate(provider: Provider): string | null;
114
+ /**
115
+ * Clear the cache for a specific provider or all providers
116
+ */
117
+ clearCache(provider?: Provider): void;
118
+ }
119
+ /**
120
+ * Get the default client instance
121
+ */
122
+ export declare function getDefaultClient(): PricingClient;
123
+ /**
124
+ * Convenience function to get model pricing using default client
125
+ */
126
+ export declare function getModelPricing(provider: Provider, modelId: string): Promise<PriceLookupResult>;
127
+ /**
128
+ * Convenience function to calculate cost using default client
129
+ */
130
+ export declare function calculateCost(provider: Provider, modelId: string, tokens: {
131
+ inputTokens: number;
132
+ outputTokens: number;
133
+ cachedInputTokens?: number;
134
+ }): Promise<CostResult>;
135
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/npm/client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,QAAQ,EACR,YAAY,EAEZ,YAAY,EACZ,oBAAoB,EACpB,iBAAiB,EACjB,UAAU,EACX,MAAM,YAAY,CAAC;AA4BpB;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;aAEzB,UAAU,EAAE,MAAM;aAClB,QAAQ,EAAE,MAAM;aAChB,QAAQ,EAAE,MAAM;gBAFhB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM;CASnC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,KAAK,CAAwC;IACrD,OAAO,CAAC,aAAa,CAAC,CAAwC;gBAElD,OAAO,GAAE,oBAAyB;IAO9C;;OAEG;IACH,OAAO,CAAC,QAAQ;IAIhB;;OAEG;IACH,OAAO,CAAC,WAAW;IAInB;;OAEG;YACW,qBAAqB;IAcnC;;OAEG;YACW,mBAAmB;IAUjC;;OAEG;YACW,aAAa;IAsD3B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAMxB;;;;;;;OAOG;IACG,eAAe,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAyBtF;;OAEG;IACG,qBAAqB,CACzB,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAQpC;;OAEG;IACG,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAKlF;;OAEG;IACG,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAKvD;;;;;;;;;OASG;IACG,aAAa,CACjB,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE;QACN,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;KAC5B,GACA,OAAO,CAAC,UAAU,CAAC;IAqCtB;;OAEG;IACG,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC;IAInE;;;OAGG;IACH,aAAa,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI;IAKhD;;OAEG;IACH,UAAU,CAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,IAAI;CAOtC;AAOD;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,CAKhD;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,iBAAiB,CAAC,CAE5B;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE;IACN,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,GACA,OAAO,CAAC,UAAU,CAAC,CAErB"}
@@ -0,0 +1,312 @@
1
+ /**
2
+ * Token Prices Client
3
+ * Fetches and caches provider pricing data with daily refresh
4
+ */
5
+ // Default URL serves from GitHub Pages when configured, falls back to raw.githubusercontent.com
6
+ // Users can override with their own GitHub Pages URL via baseUrl option
7
+ const DEFAULT_BASE_URL = 'https://raw.githubusercontent.com/mikkotikkanen/token-prices/main/docs/api/v1';
8
+ /**
9
+ * Get UTC date as YYYY-MM-DD with optional offset
10
+ */
11
+ function getUtcDate(offsetMs = 0) {
12
+ return new Date(Date.now() + offsetMs).toISOString().split('T')[0];
13
+ }
14
+ /**
15
+ * Calculate days difference between two YYYY-MM-DD dates
16
+ */
17
+ function daysDifference(dateA, dateB) {
18
+ const a = new Date(dateA + 'T00:00:00Z').getTime();
19
+ const b = new Date(dateB + 'T00:00:00Z').getTime();
20
+ return Math.floor((a - b) / (24 * 60 * 60 * 1000));
21
+ }
22
+ /**
23
+ * Error thrown when a clock mismatch is detected
24
+ */
25
+ export class ClockMismatchError extends Error {
26
+ clientDate;
27
+ dataDate;
28
+ daysDiff;
29
+ constructor(clientDate, dataDate, daysDiff) {
30
+ super(`Clock mismatch detected: client thinks it's ${clientDate} but latest data is from ${dataDate} ` +
31
+ `(${daysDiff} days difference). This may indicate your server clock is wrong. ` +
32
+ `Use the timeOffsetMs option to adjust, or check your system clock.`);
33
+ this.clientDate = clientDate;
34
+ this.dataDate = dataDate;
35
+ this.daysDiff = daysDiff;
36
+ this.name = 'ClockMismatchError';
37
+ }
38
+ }
39
+ /**
40
+ * Token Prices Client
41
+ *
42
+ * Provides access to LLM pricing data with automatic caching and daily refresh.
43
+ *
44
+ * @example
45
+ * ```ts
46
+ * import { PricingClient } from 'token-prices';
47
+ *
48
+ * const client = new PricingClient();
49
+ *
50
+ * // Get pricing for a model
51
+ * const pricing = await client.getModelPricing('openai', 'gpt-4o');
52
+ * console.log(pricing.input, pricing.output);
53
+ *
54
+ * // Calculate cost
55
+ * const cost = await client.calculateCost('anthropic', 'claude-sonnet-4', {
56
+ * inputTokens: 1000,
57
+ * outputTokens: 500,
58
+ * });
59
+ * console.log(cost.totalCost);
60
+ * ```
61
+ */
62
+ export class PricingClient {
63
+ baseUrl;
64
+ fetchFn;
65
+ timeOffsetMs;
66
+ cache = new Map();
67
+ externalCache;
68
+ constructor(options = {}) {
69
+ this.baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;
70
+ this.fetchFn = options.fetch ?? globalThis.fetch.bind(globalThis);
71
+ this.timeOffsetMs = options.timeOffsetMs ?? 0;
72
+ this.externalCache = options.externalCache;
73
+ }
74
+ /**
75
+ * Get today's date according to this client (with offset applied)
76
+ */
77
+ getToday() {
78
+ return getUtcDate(this.timeOffsetMs);
79
+ }
80
+ /**
81
+ * Get cache key for external cache
82
+ */
83
+ getCacheKey(provider) {
84
+ return `token-prices:${provider}`;
85
+ }
86
+ /**
87
+ * Try to load from external cache
88
+ */
89
+ async loadFromExternalCache(provider) {
90
+ if (!this.externalCache)
91
+ return null;
92
+ try {
93
+ const raw = await this.externalCache.get(this.getCacheKey(provider));
94
+ if (raw) {
95
+ return JSON.parse(raw);
96
+ }
97
+ }
98
+ catch {
99
+ // External cache failed, continue without it
100
+ }
101
+ return null;
102
+ }
103
+ /**
104
+ * Save to external cache
105
+ */
106
+ async saveToExternalCache(provider, entry) {
107
+ if (!this.externalCache)
108
+ return;
109
+ try {
110
+ await this.externalCache.set(this.getCacheKey(provider), JSON.stringify(entry));
111
+ }
112
+ catch {
113
+ // External cache failed, continue without it
114
+ }
115
+ }
116
+ /**
117
+ * Fetch provider data, using cache if available and fresh
118
+ */
119
+ async fetchProvider(provider) {
120
+ const today = this.getToday();
121
+ // Check in-memory cache first
122
+ let cached = this.cache.get(provider);
123
+ // If no in-memory cache, try external cache
124
+ if (!cached && this.externalCache) {
125
+ const external = await this.loadFromExternalCache(provider);
126
+ if (external) {
127
+ cached = external;
128
+ // Populate in-memory cache from external
129
+ this.cache.set(provider, external);
130
+ }
131
+ }
132
+ // If we have cached data from today, use it (don't fetch again)
133
+ if (cached && cached.fetchedDate === today) {
134
+ return cached.data;
135
+ }
136
+ // Try to fetch fresh data
137
+ const url = `${this.baseUrl}/${provider}.json`;
138
+ const response = await this.fetchFn(url);
139
+ if (!response.ok) {
140
+ // If fetch fails but we have cached data, use it
141
+ if (cached) {
142
+ return cached.data;
143
+ }
144
+ throw new Error(`Failed to fetch pricing data for ${provider}: ${response.status}`);
145
+ }
146
+ const data = (await response.json());
147
+ const daysDiff = daysDifference(today, data.current.date);
148
+ // Check for clock mismatch: data from future means our clock is behind
149
+ if (daysDiff < 0) {
150
+ throw new ClockMismatchError(today, data.current.date, daysDiff);
151
+ }
152
+ // Check for clock mismatch: data more than 1 day behind means our clock is ahead
153
+ if (daysDiff > 1) {
154
+ throw new ClockMismatchError(today, data.current.date, daysDiff);
155
+ }
156
+ // Cache the data with today's date so we don't fetch again today
157
+ const entry = { data, fetchedDate: today };
158
+ this.cache.set(provider, entry);
159
+ await this.saveToExternalCache(provider, entry);
160
+ return data;
161
+ }
162
+ /**
163
+ * Get the effective pricing data, handling the dual-date fallback
164
+ */
165
+ getEffectiveData(file) {
166
+ // Always use current - the dual-date structure is for consumers
167
+ // who want to detect if data is stale and handle it themselves
168
+ return file.current;
169
+ }
170
+ /**
171
+ * Get pricing for a specific model
172
+ *
173
+ * @param provider - The provider (openai, anthropic, google, openrouter)
174
+ * @param modelId - The model identifier
175
+ * @returns The pricing data for the model
176
+ * @throws Error if model is not found
177
+ */
178
+ async getModelPricing(provider, modelId) {
179
+ const file = await this.fetchProvider(provider);
180
+ const data = this.getEffectiveData(file);
181
+ const pricing = data.models[modelId];
182
+ if (!pricing) {
183
+ const available = Object.keys(data.models).join(', ');
184
+ throw new Error(`Model '${modelId}' not found for provider '${provider}'. Available: ${available}`);
185
+ }
186
+ // Data is stale if today's date (with offset) is newer than the data date
187
+ const today = this.getToday();
188
+ const stale = data.date < today;
189
+ return {
190
+ provider,
191
+ modelId,
192
+ pricing,
193
+ date: data.date,
194
+ stale,
195
+ };
196
+ }
197
+ /**
198
+ * Get pricing for a model, returning null if not found
199
+ */
200
+ async getModelPricingOrNull(provider, modelId) {
201
+ try {
202
+ return await this.getModelPricing(provider, modelId);
203
+ }
204
+ catch {
205
+ return null;
206
+ }
207
+ }
208
+ /**
209
+ * Get all models for a provider
210
+ */
211
+ async getProviderModels(provider) {
212
+ const file = await this.fetchProvider(provider);
213
+ return this.getEffectiveData(file).models;
214
+ }
215
+ /**
216
+ * List all model IDs for a provider
217
+ */
218
+ async listModels(provider) {
219
+ const models = await this.getProviderModels(provider);
220
+ return Object.keys(models);
221
+ }
222
+ /**
223
+ * Calculate cost for a given number of tokens
224
+ *
225
+ * @param provider - The provider
226
+ * @param modelId - The model identifier
227
+ * @param tokens - Token counts
228
+ * @param tokens.inputTokens - Number of input tokens
229
+ * @param tokens.outputTokens - Number of output tokens
230
+ * @param tokens.cachedInputTokens - Number of cached input tokens (optional)
231
+ */
232
+ async calculateCost(provider, modelId, tokens) {
233
+ const { pricing, date, stale } = await this.getModelPricing(provider, modelId);
234
+ // Validate this is a text model with token pricing
235
+ if (pricing.input === undefined || pricing.output === undefined) {
236
+ throw new Error(`Model '${modelId}' does not have token-based pricing. ` +
237
+ `Use image/audio/video pricing fields instead.`);
238
+ }
239
+ const { inputTokens, outputTokens, cachedInputTokens = 0 } = tokens;
240
+ // Calculate costs (prices are per million tokens)
241
+ const regularInputTokens = inputTokens - cachedInputTokens;
242
+ const usedCachedPricing = cachedInputTokens > 0 && pricing.cached !== undefined;
243
+ let inputCost = (regularInputTokens / 1_000_000) * pricing.input;
244
+ if (usedCachedPricing && pricing.cached !== undefined) {
245
+ inputCost += (cachedInputTokens / 1_000_000) * pricing.cached;
246
+ }
247
+ else {
248
+ // No cached pricing available, use regular input price
249
+ inputCost += (cachedInputTokens / 1_000_000) * pricing.input;
250
+ }
251
+ const outputCost = (outputTokens / 1_000_000) * pricing.output;
252
+ return {
253
+ inputCost,
254
+ outputCost,
255
+ totalCost: inputCost + outputCost,
256
+ usedCachedPricing,
257
+ date,
258
+ stale,
259
+ };
260
+ }
261
+ /**
262
+ * Get the raw provider file (includes both current and previous data)
263
+ */
264
+ async getRawProviderData(provider) {
265
+ return this.fetchProvider(provider);
266
+ }
267
+ /**
268
+ * Get the date of the currently cached data for a provider
269
+ * Returns null if no data is cached
270
+ */
271
+ getCachedDate(provider) {
272
+ const cached = this.cache.get(provider);
273
+ return cached?.data.current.date ?? null;
274
+ }
275
+ /**
276
+ * Clear the cache for a specific provider or all providers
277
+ */
278
+ clearCache(provider) {
279
+ if (provider) {
280
+ this.cache.delete(provider);
281
+ }
282
+ else {
283
+ this.cache.clear();
284
+ }
285
+ }
286
+ }
287
+ /**
288
+ * Default client instance for convenience
289
+ */
290
+ let defaultClient = null;
291
+ /**
292
+ * Get the default client instance
293
+ */
294
+ export function getDefaultClient() {
295
+ if (!defaultClient) {
296
+ defaultClient = new PricingClient();
297
+ }
298
+ return defaultClient;
299
+ }
300
+ /**
301
+ * Convenience function to get model pricing using default client
302
+ */
303
+ export async function getModelPricing(provider, modelId) {
304
+ return getDefaultClient().getModelPricing(provider, modelId);
305
+ }
306
+ /**
307
+ * Convenience function to calculate cost using default client
308
+ */
309
+ export async function calculateCost(provider, modelId, tokens) {
310
+ return getDefaultClient().calculateCost(provider, modelId, tokens);
311
+ }
312
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/npm/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Token Prices - Daily LLM pricing data
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import { getModelPricing, calculateCost } from 'token-prices';
7
+ *
8
+ * // Get pricing for a model
9
+ * const result = await getModelPricing('openai', 'gpt-4o');
10
+ * console.log(`Input: $${result.pricing.input}/M tokens`);
11
+ * console.log(`Output: $${result.pricing.output}/M tokens`);
12
+ *
13
+ * // Calculate cost for an API call
14
+ * const cost = await calculateCost('anthropic', 'claude-sonnet-4', {
15
+ * inputTokens: 1500,
16
+ * outputTokens: 800,
17
+ * });
18
+ * console.log(`Total cost: $${cost.totalCost.toFixed(6)}`);
19
+ * ```
20
+ *
21
+ * @packageDocumentation
22
+ */
23
+ export type { ModelPricing, ProviderData, ProviderFile, Provider, PricingClientOptions, PriceLookupResult, CostResult, } from './types.js';
24
+ export { PricingClient, ClockMismatchError, getDefaultClient, getModelPricing, calculateCost, } from './client.js';
25
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/npm/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,QAAQ,EACR,oBAAoB,EACpB,iBAAiB,EACjB,UAAU,GACX,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,aAAa,GACd,MAAM,aAAa,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Token Prices - Daily LLM pricing data
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import { getModelPricing, calculateCost } from 'token-prices';
7
+ *
8
+ * // Get pricing for a model
9
+ * const result = await getModelPricing('openai', 'gpt-4o');
10
+ * console.log(`Input: $${result.pricing.input}/M tokens`);
11
+ * console.log(`Output: $${result.pricing.output}/M tokens`);
12
+ *
13
+ * // Calculate cost for an API call
14
+ * const cost = await calculateCost('anthropic', 'claude-sonnet-4', {
15
+ * inputTokens: 1500,
16
+ * outputTokens: 800,
17
+ * });
18
+ * console.log(`Total cost: $${cost.totalCost.toFixed(6)}`);
19
+ * ```
20
+ *
21
+ * @packageDocumentation
22
+ */
23
+ // Re-export client
24
+ export { PricingClient, ClockMismatchError, getDefaultClient, getModelPricing, calculateCost, } from './client.js';
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/npm/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAaH,mBAAmB;AACnB,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,aAAa,GACd,MAAM,aAAa,CAAC"}
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Token Prices NPM Module Types
3
+ */
4
+ /**
5
+ * Variant pricing for resolution/quality dependent models
6
+ */
7
+ export interface VariantPricing {
8
+ /** Input cost for this variant */
9
+ input?: number;
10
+ /** Output cost for this variant */
11
+ output?: number;
12
+ }
13
+ /**
14
+ * Pricing data for a single model
15
+ */
16
+ export interface ModelPricing {
17
+ /** Price per 1M input tokens in USD */
18
+ input?: number;
19
+ /** Price per 1M output tokens in USD */
20
+ output?: number;
21
+ /** Price per 1M cached input tokens in USD (if supported) */
22
+ cached?: number;
23
+ /** Context window size in tokens */
24
+ context?: number;
25
+ /** Maximum output tokens */
26
+ maxOutput?: number;
27
+ /** Image pricing by resolution/quality (per image) */
28
+ image?: Record<string, VariantPricing>;
29
+ /** Audio pricing by quality (per minute) */
30
+ audio?: Record<string, VariantPricing>;
31
+ /** Video pricing by resolution (per second) */
32
+ video?: Record<string, VariantPricing>;
33
+ }
34
+ /**
35
+ * Provider pricing data for a single date
36
+ */
37
+ export interface ProviderData {
38
+ /** ISO date string (YYYY-MM-DD) */
39
+ date: string;
40
+ /** Model pricing map: modelId -> pricing */
41
+ models: Record<string, ModelPricing>;
42
+ }
43
+ /**
44
+ * Dual-date structure for handling update timing
45
+ * When fetching on a new day, if current.date hasn't updated yet,
46
+ * the previous data is still valid to use
47
+ */
48
+ export interface ProviderFile {
49
+ /** Current/latest pricing data */
50
+ current: ProviderData;
51
+ /** Previous day's data (for fallback during updates) */
52
+ previous?: ProviderData;
53
+ }
54
+ /**
55
+ * Supported providers
56
+ */
57
+ export type Provider = 'openai' | 'anthropic' | 'google' | 'openrouter';
58
+ /**
59
+ * Options for the pricing client
60
+ */
61
+ export interface PricingClientOptions {
62
+ /**
63
+ * Base URL for fetching pricing data
64
+ * @default 'https://raw.githubusercontent.com/mikkotikkanen/token-prices/main/docs/api/v1'
65
+ */
66
+ baseUrl?: string;
67
+ /**
68
+ * Custom fetch function (for testing or special environments)
69
+ */
70
+ fetch?: typeof globalThis.fetch;
71
+ /**
72
+ * Time offset in milliseconds to adjust the client's "today" calculation.
73
+ * Use this if the server clock is known to be off.
74
+ * Positive values move time forward, negative values move it back.
75
+ * @example
76
+ * // Server clock is 2 hours behind UTC
77
+ * new PricingClient({ timeOffsetMs: 2 * 60 * 60 * 1000 })
78
+ */
79
+ timeOffsetMs?: number;
80
+ /**
81
+ * External cache for persisting fetch timestamps across restarts/instances.
82
+ * If not provided, uses in-memory cache (lost on restart).
83
+ *
84
+ * This prevents hammering GitHub when:
85
+ * - Running in serverless (cold starts)
86
+ * - Multiple server instances
87
+ * - Server restarts
88
+ *
89
+ * @example
90
+ * // Using a simple file-based cache
91
+ * const cacheFile = './price-cache.json';
92
+ * new PricingClient({
93
+ * externalCache: {
94
+ * get: async (key) => {
95
+ * try {
96
+ * const data = JSON.parse(fs.readFileSync(cacheFile, 'utf8'));
97
+ * return data[key];
98
+ * } catch { return undefined; }
99
+ * },
100
+ * set: async (key, value) => {
101
+ * let data = {};
102
+ * try { data = JSON.parse(fs.readFileSync(cacheFile, 'utf8')); } catch {}
103
+ * data[key] = value;
104
+ * fs.writeFileSync(cacheFile, JSON.stringify(data));
105
+ * }
106
+ * }
107
+ * });
108
+ */
109
+ externalCache?: {
110
+ get: (key: string) => Promise<string | undefined> | string | undefined;
111
+ set: (key: string, value: string) => Promise<void> | void;
112
+ };
113
+ }
114
+ /**
115
+ * Result of a price lookup
116
+ */
117
+ export interface PriceLookupResult {
118
+ /** The provider */
119
+ provider: Provider;
120
+ /** The model ID */
121
+ modelId: string;
122
+ /** The pricing data */
123
+ pricing: ModelPricing;
124
+ /** The date of the pricing data (YYYY-MM-DD) */
125
+ date: string;
126
+ /** True if the data is from a previous day (new data not yet available) */
127
+ stale: boolean;
128
+ }
129
+ /**
130
+ * Calculate cost result
131
+ */
132
+ export interface CostResult {
133
+ /** Cost for input tokens in USD */
134
+ inputCost: number;
135
+ /** Cost for output tokens in USD */
136
+ outputCost: number;
137
+ /** Total cost in USD */
138
+ totalCost: number;
139
+ /** Whether cached pricing was used for input */
140
+ usedCachedPricing: boolean;
141
+ /** The date of the pricing data used (YYYY-MM-DD) */
142
+ date: string;
143
+ /** True if the pricing data is from a previous day */
144
+ stale: boolean;
145
+ }
146
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/npm/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,kCAAkC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,uCAAuC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oCAAoC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACvC,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACvC,+CAA+C;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CACxC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CACtC;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,kCAAkC;IAClC,OAAO,EAAE,YAAY,CAAC;IACtB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,YAAY,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,YAAY,CAAC;AAExE;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAChC;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACH,aAAa,CAAC,EAAE;QACd,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,GAAG,MAAM,GAAG,SAAS,CAAC;QACvE,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;KAC3D,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,mBAAmB;IACnB,QAAQ,EAAE,QAAQ,CAAC;IACnB,mBAAmB;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,uBAAuB;IACvB,OAAO,EAAE,YAAY,CAAC;IACtB,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,2EAA2E;IAC3E,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,wBAAwB;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,iBAAiB,EAAE,OAAO,CAAC;IAC3B,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,KAAK,EAAE,OAAO,CAAC;CAChB"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Token Prices NPM Module Types
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/npm/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "token-costs",
3
+ "version": "1.0.0",
4
+ "description": "Daily LLM token pricing data with automatic updates",
5
+ "type": "module",
6
+ "main": "dist/npm/index.js",
7
+ "types": "dist/npm/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/npm/index.js",
11
+ "types": "./dist/npm/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist/npm/**/*"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsc",
19
+ "dev": "npm run build && npm run crawl:all",
20
+ "dev:openai": "npm run build && npm run crawl:openai",
21
+ "dev:anthropic": "npm run build && npm run crawl:anthropic",
22
+ "dev:google": "npm run build && npm run crawl:google",
23
+ "dev:openrouter": "npm run build && npm run crawl:openrouter",
24
+ "test": "vitest run",
25
+ "test:watch": "vitest",
26
+ "test:coverage": "vitest run --coverage",
27
+ "crawl:openai": "node --experimental-vm-modules dist/crawlers/openai/index.js",
28
+ "crawl:anthropic": "node --experimental-vm-modules dist/crawlers/anthropic/index.js",
29
+ "crawl:google": "node --experimental-vm-modules dist/crawlers/google/index.js",
30
+ "crawl:openrouter": "node --experimental-vm-modules dist/crawlers/openrouter/index.js",
31
+ "crawl:all": "npm run crawl:openai && npm run crawl:anthropic && npm run crawl:google && npm run crawl:openrouter",
32
+ "show:openai": "node -e \"const fs=require('fs');const d=JSON.parse(fs.readFileSync('./history/prices/openai.json','utf8'));console.log(JSON.stringify(d,null,2));\"",
33
+ "show:anthropic": "node -e \"const fs=require('fs');const d=JSON.parse(fs.readFileSync('./history/prices/anthropic.json','utf8'));console.log(JSON.stringify(d,null,2));\"",
34
+ "show:google": "node -e \"const fs=require('fs');const d=JSON.parse(fs.readFileSync('./history/prices/google.json','utf8'));console.log(JSON.stringify(d,null,2));\"",
35
+ "show:openrouter": "node -e \"const fs=require('fs');const d=JSON.parse(fs.readFileSync('./history/prices/openrouter.json','utf8'));console.log(JSON.stringify(d,null,2));\"",
36
+ "test:local": "npm run build && node --experimental-vm-modules dist/test-local.js",
37
+ "test:local:openai": "npm run build && node --experimental-vm-modules dist/test-local.js openai",
38
+ "test:local:anthropic": "npm run build && node --experimental-vm-modules dist/test-local.js anthropic",
39
+ "test:local:google": "npm run build && node --experimental-vm-modules dist/test-local.js google",
40
+ "test:local:openrouter": "npm run build && node --experimental-vm-modules dist/test-local.js openrouter",
41
+ "test:local:show": "npm run build && node --experimental-vm-modules dist/test-local.js --show",
42
+ "generate:npm": "npm run build && node dist/generate-npm-files.js",
43
+ "prepublishOnly": "npm run build && npm test"
44
+ },
45
+ "repository": {
46
+ "type": "git",
47
+ "url": "https://github.com/mikkotikkanen/token-costs.git"
48
+ },
49
+ "homepage": "https://mikkotikkanen.github.io/token-costs",
50
+ "bugs": {
51
+ "url": "https://github.com/mikkotikkanen/token-costs/issues"
52
+ },
53
+ "keywords": [
54
+ "llm",
55
+ "pricing",
56
+ "openai",
57
+ "anthropic",
58
+ "google",
59
+ "openrouter",
60
+ "gpt",
61
+ "claude",
62
+ "gemini",
63
+ "tokens",
64
+ "cost"
65
+ ],
66
+ "author": "Mikko Tikkanen",
67
+ "license": "MIT",
68
+ "devDependencies": {
69
+ "@types/node": "^20.10.0",
70
+ "cheerio": "^1.0.0-rc.12",
71
+ "node-fetch": "^3.3.2",
72
+ "typescript": "^5.3.0",
73
+ "vitest": "^1.0.0"
74
+ },
75
+ "engines": {
76
+ "node": ">=20.0.0"
77
+ }
78
+ }