Web API History Series • Post 75 of 240
Chapter 75: Cookies, Sessions, and Stateful Web Apps (1995–1998)—How Early Web APIs Learned to Remember
A chronological, SEO-focused guide to Cookies, sessions, and stateful web applications in web API history and its role in the long evolution of web APIs.
Chapter 75: Cookies, Sessions, and Stateful Web Apps (1995–1998)—How Early Web APIs Learned to Remember
In the mid-to-late 1990s, the web’s biggest limitation wasn’t bandwidth or graphics. It was memory—specifically, the fact that HTTP was designed to be stateless. Each request could be handled in isolation, which made servers simpler and the protocol resilient. But that same statelessness made it hard to build anything that felt like an “application.”
From roughly 1995 through 1998, a set of pragmatic techniques—HTML forms, CGI scripts, URL parameters, early browser scripting, and eventually HTTP cookies—formed the foundation of stateful web applications and the API patterns we still use today.
Stateless HTTP Meets a Stateful World
HTTP’s stateless model was a feature, not a bug: the server didn’t have to remember who you were between requests. The problem was that users absolutely expected continuity. If you added something to a cart, navigated through a multi-page form, or authenticated to see private data, you expected the site to “remember” you.
In API terms, early web developers needed an identity handle that could flow through a series of requests. They also needed a server-side place to store evolving data across those requests. The late-1990s solution ended up being a split brain:
- A client-side token (eventually most commonly a cookie) to label the browser.
- A server-side session store keyed by that token, containing cart contents, authentication state, or workflow progress.
This “token + session store” model shaped web API thinking for years, influencing how developers designed endpoints, validated requests, and reasoned about authentication.
1995: Forms, CGI, and the First Practical “API Calls”
By the time 1995 rolled around, HTML forms were turning websites into input-driven systems. A form submission—via GET or POST—was effectively a remote procedure call from the browser to the server. It wasn’t called an “API request” by most people yet, but it played the same role: structured client input, structured server output, and an implied contract.
On many servers, those submissions landed in CGI programs. CGI didn’t standardize business logic, frameworks, or routing the way modern platforms do, but it did standardize something that matters for API history: the boundary between the web server and a program that can read request data and emit a response.
CGI scripts could read query strings and POST bodies, then generate HTML dynamically. But they were usually invoked per request, which made persistence tricky. Developers used several patterns to simulate state:
- Hidden form fields to carry data forward, step by step.
- URL parameters (query strings) that encoded choices and identifiers.
- Server-side storage keyed by something passed in from the client (often a parameter embedded in the URL).
These were early lessons in a key API principle: if your protocol doesn’t carry state, your application must. Web APIs needed a repeatable way to correlate multiple requests with one user journey.
1995–1996: Browser Scripting Adds a Second “Runtime”
JavaScript (introduced in the mid-1990s) changed the shape of web interactions, even before modern AJAX existed. Client-side validation reduced unnecessary round trips. Simple dynamic behaviors—show/hide elements, compute totals, validate fields—made the browser feel more like an application shell than a document viewer.
But browser scripting also added pressure to make server interactions more consistent. When a page included scripts that depended on predictable server output, developers started thinking in contracts: which parameters are expected, what values are allowed, what the server will return if validation fails, and how errors should be represented.
Even without JSON, the mindset was becoming API-like. Responses were still HTML, but the process was increasingly programmatic: forms fed scripts; scripts shaped user input; input triggered server logic; server logic created dynamic pages. Stateful behavior became the glue that kept the whole system coherent.
Before Cookies: URL Rewriting and Its Tradeoffs
Before cookies became widespread, one of the most common state tricks was URL rewriting: the server would generate links like /checkout?session=ABC123 or even embed identifiers inside path segments. Every subsequent click carried the session identifier forward.
URL rewriting worked, but it had significant downsides that influenced later web API security practices:
- Leaky identifiers: session IDs could show up in browser history, server logs, bookmarks, or shared links.
- Accidental propagation: users could copy/paste a URL to someone else and unintentionally share access.
- Cache confusion: intermediaries and proxies could cache pages keyed by URLs that contained sensitive state.
These issues didn’t disappear with cookies, but cookies changed the default flow of identity. Instead of placing state in the URL where it was visible and shareable, state could be placed in request headers—still transmitted, but less likely to be casually copied.
1996–1998: Cookies Become the Web’s State Mechanism
Cookies began as a browser-driven mechanism to store small pieces of data and send them back to a site on subsequent requests. Netscape’s early implementation popularized the approach, and by the late 1990s cookies were becoming a common ingredient in login systems, personalization, and shopping carts.
Critically for web API history, cookies weren’t just about convenience—they introduced a standardized, automated way to attach client identity to every request. This made it far easier to build server-side sessions reliably.
In practice, most sites used cookies as a pointer, not as a database. A typical late-1990s pattern looked like this:
- The server creates a session record (in memory, a file, or a database).
- The server sends a cookie containing a session identifier.
- The browser automatically includes that cookie on subsequent requests to the same site.
- The server reads the cookie, looks up the session, and continues the workflow.
In 1997, the IETF published RFC 2109, an early attempt to standardize cookie behavior more formally. The details evolved later, but the late-1990s period is when “cookie + session” became the dominant mental model for stateful web applications.
If you want a modern, developer-focused explanation of cookies that connects today’s mechanics back to those early patterns, MDN’s documentation is a solid reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies.
Why This Mattered for Web APIs (Even Before “Web API” Was a Common Term)
Between 1995 and 1998, the web learned a lesson that every API designer still lives with: state has to live somewhere. The choices made during this era created conventions that remained dominant long after XML and JSON appeared.
Here are the API-level implications that emerged from this period:
- Identity becomes implicit: with cookies, the server can recognize a browser without the client explicitly adding a user ID parameter to every request.
- Server memory shapes UX: sessions enabled multi-step processes (checkout flows, wizards) that would be painful with only URL parameters.
- Security becomes an application concern: session fixation, hijacking, and leakage became practical problems, not theoretical ones.
- Contracts become necessary: as sites got more dynamic and scripted, consistent request/response behavior mattered—an early precursor to formal API specifications.
Even the simplest CGI-backed application started to resemble a set of endpoints. The moment those endpoints relied on sessions, developers needed patterns for expiration, invalidation, and error handling. That operational mindset is part of what turned the web from a document system into an application platform.
Early Dynamic Integration: Putting It All Together
The most common “stateful stack” of the era combined:
- HTML forms for user input and parameter passing
- CGI (or server extensions) for dynamic processing
- JavaScript for client-side validation and lightweight interaction
- Cookies for client identification
- Server sessions for continuity and business logic
This combination produced recognizable application behaviors: authenticated areas, shopping carts, personalization, and multi-page workflows. It also shaped how developers thought about “state” as a shared responsibility between client and server—one that had to be managed deliberately to avoid breaking user journeys.
If you’re exploring how automation and modern tooling intersects with these foundational web mechanics—especially around request handling, repeatability, and the realities of state—see more at https://automatedhacks.com/.
What Changed After 1998 (A Brief Look Ahead)
By the end of the 1990s, the cookie-and-session model was established enough that it became the default assumption for many web applications. In the years that followed, developers layered new response formats (like XML) and richer client interactions on top of the same state foundations.
In other words: when modern web APIs later debated “stateless REST” versus “session-based apps,” they were reacting to a model that had already won the practical usability battle back in the 1995–1998 era.
FAQ: Cookies, Sessions, and Early Web API History
Were early web applications truly using APIs?
They weren’t usually described that way, but form submissions to CGI scripts acted like API calls: a structured request with parameters, a predictable response, and an implied contract between client and server.
Why didn’t developers just store everything in the browser?
In that era, client-side storage options were limited, inconsistent across browsers, and not designed for complex application state. Cookies could store small values, but most serious state lived on the server in sessions.
Did cookies replace URL-based sessions completely?
No. URL rewriting remained a fallback, especially when cookies were disabled or unreliable. But cookies quickly became the preferred mechanism because they reduced accidental sharing and cleaned up URLs.
What’s the key lesson from 1995–1998 for API designers today?
State management is never “free.” Whether you choose cookies, tokens, or fully stateless designs, you must plan how identity is carried, how state is stored, and how it expires—because user experience depends on continuity.
