REST API Documentation

Access 4.2 million archived web pages from 1990โ€“1999 programmatically. Search, retrieve, index, and manage archived content via our RESTful API.

BASE URL: https://api.1990webarchive.com/v1

๐Ÿ”‘ Authentication

The 1990 Web Archive API uses Bearer token authentication. Include your API key in the Authorization header of every request.

http
Authorization: Bearer sk_live_1990a2b3c4d5e6f7g8h9i0j1 Content-Type: application/json X-Archive-Source: github-bot
โš ๏ธ Keep your API keys secure. Never expose them in client-side code or public repositories. Use environment variables in production.

Auth Method

Method Header Description
Bearer Token Authorization Bearer token prefixed with Bearer
API Key X-API-Key Alternative header-based authentication

๐Ÿ” API Keys

Manage your API keys from the Developer Dashboard. Each key has an associated tier that determines rate limits and access levels.

Key Prefix Environment Purpose
sk_live_ Production Live archive access with full crawl permissions
sk_test_ Sandbox Read-only access to sample data for testing
sk_restricted_ Scoped Limited access to specific archive collections

โฑ๏ธ Rate Limiting

API requests are rate limited based on your plan tier. Limits are tracked per API key and reset at the top of each time window.

๐Ÿ“Š Rate Limit Tiers

  • Free: 100 requests / hour โ€” read-only access
  • Pro: 5,000 requests / hour โ€” full read access + indexing
  • Enterprise: 50,000 requests / hour โ€” unlimited indexing + webhooks

Response Headers

Every API response includes rate limit headers:

headers
X-RateLimit-Limit: 5000 X-RateLimit-Remaining: 4973 X-RateLimit-Reset: 1704067200 X-RateLimit-Window: 3600
โ„น๏ธ When rate limit is exceeded, the API returns HTTP 429 Too Many Requests. Implement exponential backoff in your retry logic.

๐Ÿ“Œ API Versioning

The current API version is v1, embedded in the base URL. We maintain backward compatibility within major versions.

http
// Current stable version https://api.1990webarchive.com/v1//pages/search // Version pinned to a specific release https://api.1990webarchive.com/v1.2//pages/search

๐Ÿ“„ Retrieve Archived Page

GET /pages/:archive_id Retrieve the full metadata and content of a specific archived page.

Path Parameters

Parameter Type Required Description
archive_id string Yes The unique archive identifier (e.g., arc_gtc_00482195)

Query Parameters

Parameter Type Required Description
format string No Output format: json, html, html-raw, pdf. Default: json.
render_assets boolean No Include base64-encoded images. Default: false.
embed_midi boolean No Include embedded MIDI audio tracks. Default: true.

Example Request

http
GET /v1/pages/arc_gtc_00482195?format=json&render_assets=true

Example Response

200 OK
json
{ "status": "success", "data": { "id": "arc_gtc_00482195", "original_url": "http://geocities.com/SunsetStrip/Club/6285/", "snapshot_date": "1995-08-12T00:00:00Z", "title": "Welcome to My Homepage!!!", "html_content": "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 3.2//EN'>...", "content_length": 12847, "mime_type": "text/html", "technologies": ["frames", "table-layout", "animated-gifs", "marquee"], "meta_tags": { "keywords": "homepage, personal, welcome, guestbook", "description": "Welcome to my awesome homepage!!", "generator": "Microsoft FrontPage 3.0" }, "images": [ { "src": "http://geocities.com/SunsetStrip/Club/6285/images/counter.gif", "width": 88, "height": 31, "type": "animated-gif", "base64": "data:image/gif;base64,R0lGODlh..." } ], "linked_pages": [ "http://geocities.com/SunsetStrip/Club/6285/guestbook.html", "http://geocities.com/SunsetStrip/Club/6285/links.html" ], "verification": { "sha256": "a3f2b8c9d1e4f5a6b7c8d9e0f1a2b3c4...", "verified": true, "integrity_hash": "blake3:7x9k2m4p6q8r..." } } }

๐ŸŒ Index URL

POST /pages/index Submit a URL for archival. The archive will crawl and store the page content at the specified timestamp.

Request Body

json
{ "url": "http://www.example.com/page.html", "timestamp": "1996-03-15T12:00:00Z", "crawl_options": { "follow_frames": true, "capture_images": true, "capture_stylesheets": true, "screenshot": true, "screenshot_format": "png" }, "tags": ["personal", "1996", "example"] }

Example Response

202 Accepted
json
{ "status": "accepted", "data": { "job_id": "job_idx_1990_abc123", "status": "queued", "estimated_completion": "1996-03-15T12:05:00Z", "webhook_url": "https://api.1990webarchive.com/v1/jobs/job_idx_1990_abc123" } }

๐Ÿ“ฆ Batch Index

POST /pages/batch-index Submit up to 1,000 URLs for simultaneous archival in a single request.

Request Body

json
{ "urls": [ { "url": "http://geocities.com/Area51/Cavern/2937/", "timestamp": "1997-06-20T00:00:00Z", "tags": ["geocities", "1997"] }, { "url": "http://angelfire.com/flame/pets/index.html", "timestamp": "1998-01-10T00:00:00Z", "tags": ["angelfire", "1998"] } ], "crawl_options": { "parallel_workers": 5 } }
โš ๏ธ Batch requests are limited to 1,000 URLs per request. Enterprise plans support up to 10,000 URLs.

๐Ÿ“ Create Archive Collection

POST /archives Create a named archive collection to group related pages for organization and bulk operations.

Request Body

json
{ "name": "GeoCities SunsetStrip Collection", "description": "Archived personal homepages from the SunsetStrip area of GeoCities, 1995-1997", "source_ids": [ "arc_gtc_00482195", "arc_gtc_00591234", "arc_gtc_00678901" ], "access": "public" }

Example Response

201 Created
json
{ "status": "success", "data": { "id": "arc_col_1990_xyz789", "name": "GeoCities SunsetStrip Collection", "page_count": 3, "access": "public", "created_at": "2024-01-15T10:30:00Z", "public_url": "https://archive.1990webarchive.com/collections/arc_col_1990_xyz789" } }

๐Ÿ“š List Archives

GET /archives Retrieve a paginated list of archive collections owned by your account.

Query Parameters

Parameter Type Required Description
page integer No Page number. Default: 1.
per_page integer No Results per page (1โ€“100). Default: 20.
sort string No Sort by: created_at, name, page_count.

Example Response

200 OK
json
{ "status": "success", "meta": { "total": 12, "page": 1, "per_page": 20 }, "data": [ { "id": "arc_col_1990_xyz789", "name": "GeoCities SunsetStrip Collection", "page_count": 1847, "created_at": "2024-01-15T10:30:00Z", "access": "public" } ] }

๐Ÿ—‘๏ธ Delete Archive

DELETE /archives/:archive_id Permanently delete an archive collection. This action cannot be undone.
๐Ÿšจ DANGER: Deleting an archive permanently removes all references and breaks public sharing links. Consider creating a "deleted" status archive instead.

Example Response

200 OK
json
{ "status": "success", "data": { "message": "Archive arc_col_1990_xyz789 has been permanently deleted.", "pages_removed": 1847 } }

๐Ÿ“ธ Create Snapshot

POST /snapshots Create a visual snapshot (screenshot) of an archived page as it would appear in a 1990s browser.

Request Body

json
{ "archive_id": "arc_gtc_00482195", "browser_emulation": "netscape-4.7", "display_mode": "1024x768", "format": "png", "render_javascript": true, "embed_plugins": true }

Example Response

201 Created
json
{ "status": "success", "data": { "snapshot_id": "snap_1990_abc456", "screenshot_url": "https://archive.1990webarchive.com/snapshots/snap_1990_abc456.png", "width": 1024, "height": 768, "file_size": 2847291, "browser": "Netscape Navigator 4.7" } }

๐Ÿ”„ Compare Snapshots

GET /snapshots/compare Compare two archived snapshots of the same page from different dates and visualize differences.

Query Parameters

Parameter Type Required Description
page_id string Yes The archive page ID to compare.
snapshot_1 string Yes First snapshot ID.
snapshot_2 string Yes Second snapshot ID.
diff_type string No Diff method: html, visual, both. Default: both.

Example Response

200 OK
json
{ "status": "success", "data": { "page_id": "arc_gtc_00482195", "snapshots": { "snapshot_1": { "id": "snap_1990_abc456", "date": "1995-08-12" }, "snapshot_2": { "id": "snap_1990_def789", "date": "1997-03-22" } }, "diff": { "html_lines_added": 47, "html_lines_removed": 12, "new_images": 5, "removed_images": 2, "visual_diff_url": "https://archive.1990webarchive.com/diffs/arc_gtc_00482195.png" } } }

๐Ÿ“Š Archive Analytics

GET /analytics/:archive_id Retrieve usage analytics and access statistics for your archive collections.

Query Parameters

Parameter Type Required Description
start_date string No ISO 8601 date. Default: 30 days ago.
end_date string No ISO 8601 date. Default: today.
granularity string No Data granularity: day, week, month. Default: day.

Example Response

200 OK
json
{ "status": "success", "data": { "total_requests": 12847, "unique_visitors": 3291, "top_pages": [ { "page_id": "arc_gtc_00482195", "title": "Welcome to My Homepage!!!", "views": 2847 } ], "top_referrers": [ { "source": "google.com", "count": 4521 } ], "daily_timeline": [ {"date": "2024-01-01", "requests": 412}, {"date": "2024-01-02", "requests": 389}, {"date": "2024-01-03", "requests": 445} ] } }

๐Ÿ”” Webhooks

Configure webhook endpoints to receive real-time notifications for archive events. Enterprise plans support up to 10 webhook endpoints.

Create Webhook Endpoint

http
POST /webhooks Authorization: Bearer sk_live_... Content-Type: application/json // Body { "url": "https://your-server.com/webhooks/archive-events", "events": ["archive.completed", "archive.failed", "batch.done"], "secret": "whsec_your_webhook_secret_1990" }
โ„น๏ธ Webhook payloads are signed with HMAC-SHA256. Verify the signature using the X-Webhook-Signature header and your configured secret.

Supported Events

archive.indexed
Triggered when a page has been successfully archived and indexed. Payload includes the archive ID and crawl metadata.
archive.failed
Triggered when archival fails (404, timeout, blocked). Payload includes the error code and retry status.
batch.completed
Triggered when a batch indexing job is complete. Payload includes per-URL results and aggregate stats.
snapshot.ready
Triggered when a visual snapshot has been generated. Payload includes the screenshot URL and dimensions.
archive.deleted
Triggered when an archive collection is permanently deleted.

โšก Error Codes

The API uses standard HTTP status codes and returns structured error responses in JSON format.

json
// Standard Error Response { "status": "error", "error": { "code": "page_not_found", "message": "The requested archive page could not be found.", "doc_url": "https://docs.1990webarchive.com/errors/page_not_found" } }

All Error Codes

HTTP Status Error Code Description
400invalid_requestMalformed request body or missing required parameters
401unauthorizedInvalid or expired API key
403forbiddenInsufficient permissions for the requested resource
404page_not_foundArchive page or collection not found
409already_indexedURL is already in the archive at the requested timestamp
422crawl_failedUnable to reach the target URL for crawling
429rate_limitedToo many requests โ€” check X-RateLimit headers
500internal_errorServer error โ€” please retry and contact support if persistent
503service_unavailableAPI maintenance in progress

๐Ÿ“ฆ SDKs & Libraries

Official SDKs are available for popular languages. All SDKs are open source on GitHub.

Language Package GitHub
JavaScript / Node.js 1990webarchive github.com/1990webarchive/js-sdk
Python pip install 1990webarchive github.com/1990webarchive/py-sdk
Ruby gem install 1990webarchive github.com/1990webarchive/rb-sdk
Go go get github.com/1990webarchive/go-sdk github.com/1990webarchive/go-sdk
Rust 1990webarchive = "0.3" github.com/1990webarchive/rs-sdk

Quick Start โ€” JavaScript

javascript
import { WebArchive } from '1990webarchive'; const archive = new WebArchive({ apiKey: process.env.ARCHIVE_API_KEY }); // Search archived pages const results = await archive.pages.search({ q: 'personal homepage', start_year: 1995, per_page: 10 }); console.log(`Found ${results.meta.total_results} pages`); // Retrieve a specific page const page = await archive.pages.retrieve('arc_gtc_00482195'); console.log(page.data.title); // "Welcome to My Homepage!!!"

Quick Start โ€” Python

python
from 1990webarchive import WebArchive archive = WebArchive(api_key="sk_live_1990a2b3c4d5e6f7") # Search archived pages results = archive.pages.search( q="personal homepage", start_year=1995, per_page=10 ) print(f"Found {results['meta']['total_results']} pages") # Retrieve a specific page page = archive.pages.retrieve("arc_gtc_00482195") print(page["data"]["title"]) # "Welcome to My Homepage!!!"