1990 Web Archive SDK
Official JavaScript/TypeScript client for accessing, rendering, and analyzing historical web content from 1990–1999. Built for developers, researchers, and digital preservationists.
dashboard.1990webarchive.dev to get started with your free tier (1,000 requests/month).
Installation
Install the SDK via your preferred package manager:
# npm
npm install @1990webarchive/sdk
# yarn
yarn add @1990webarchive/sdk
# pnpm
pnpm add @1990webarchive/sdk
Quick Start
Initialize the client and fetch your first archived webpage in under 30 seconds:
import { ArchiveClient } from '@1990webarchive/sdk';
const client = new ArchiveClient({
apiKey: process.env.WA_API_KEY,
region: 'us-east', // optional
retries: 2 // default
});
async function main() {
// Fetch a snapshot from 1996
const snapshot = await client.fetchSnapshot({
url: 'https://www.yahoo.com',
date: '1996-12-15',
format: 'html'
});
console.log(snapshot.timestamp); // "1996-12-15T08:30:00Z"
console.log(snapshot.content); // "<html>..."
}
main();
Client Setup
The ArchiveClient is the main entry point for all SDK operations. It handles authentication, rate limiting, retries, and request serialization automatically.
| Parameter | Type | Description |
|---|---|---|
| apiKey | string | Required. Your secret API key from the dashboard. |
| region | string | Optional. API region endpoint. Defaults to closest. |
| timeout | number | Request timeout in ms. Defaults to 5000. |
| retries | number | Auto-retry count on 429/5xx errors. Defaults to 2. |
fetchSnapshot()
Retrieves a historically accurate snapshot of a URL at a specific point in time.
SnapshotResponse object containing the raw HTML, metadata, and resource fingerprints.| Option | Type | Description |
|---|---|---|
| url | string | Original URL to archive. Supports http://, ftp://, gopher:// |
| date | string | ISO 8601 date string. Must fall within 1990-01-01 to 1999-12-31. |
| format | 'html'|'text'|'meta' | Response format. Defaults to 'html'. 'meta' returns only headers. |
| includeAssets | boolean | If true, bundles linked CSS/JS/Images into a single payload. Defaults to false. |
interface SnapshotResponse {
id: string;
url: string;
timestamp: string;
status: number;
content: string;
metadata: {
mimeType: string;
server: string;
charset: string;
fileSize: number;
};
resources: string[]; // hashed asset URLs if includeAssets=true
}
renderLegacyPage()
Generates a modern, self-contained HTML document that renders legacy pages accurately using sandboxed iframe emulation and vintage user-agent injection.
searchIndex()
Query the historical index using era-specific filters, content tags, and visual pattern matching.
const results = await client.searchIndex({
query: 'under construction',
filters: {
yearRange: [1996, 1999],
hasGuestbook: true,
webRing: ['coolstuff', 'geocities'],
browserTarget: ['netscape3', 'ie4']
},
limit: 20
});
console.log(results.count); // 14203
console.log(results.items[0].url); // "http://home.netscape.com/..."
Request Options
All API methods accept an optional AbortSignal for cancellation and a customHeaders map for overriding default request headers. The SDK automatically attaches your API key to the Authorization: Bearer header.
Rate Limits
The API enforces tiered rate limits to ensure stable access to historical infrastructure:
- Free Tier: 1,000 requests/month, 10 req/min
- Developer: 50,000 requests/month, 60 req/min
- Research: 1,000,000 requests/month, 120 req/min
- Enterprise: Unlimited (dedicated instance)
Responses include X-RateLimit-Remaining and X-RateLimit-Reset headers. The SDK handles exponential backoff automatically for 429 responses.
Error Handling
The SDK throws typed error classes for predictable catch blocks:
import {
ArchiveError,
AuthenticationError,
RateLimitError,
SnapshotNotFoundError
} from '@1990webarchive/sdk';
try {
await client.fetchSnapshot({ url: 'http://oldsite.com', date: '1995-01-01' });
} catch (err) {
if (err instanceof SnapshotNotFoundError) {
console.log('No archive exists for this URL/date');
} else if (err instanceof RateLimitError) {
console.log('Wait', err.retryAfter, 'seconds');
} else {
console.error(err.message);
}
}