diff --git a/README.md b/README.md
index a7a88254fa..969d2b8c5d 100755
--- a/README.md
+++ b/README.md
@@ -245,6 +245,7 @@ List of Definitions
* [websocket](https://github.com/Worlize/WebSocket-Node) (by [Paul Loyd](https://github.com/loyd))
* [WinJS](http://msdn.microsoft.com/en-us/library/windows/apps/br229773.aspx) (from TypeScript samples)
* [WinRT](http://msdn.microsoft.com/en-us/library/windows/apps/br211377.aspx) (from TypeScript samples)
+* [ws](http://einaros.github.io/ws/) (by [Paul Loyd](https://github.com/loyd))
* [YouTube](https://developers.google.com/youtube/) (by [Daz Wilkin](https://github.com/DazWilkin/))
* [YouTube Analytics API](https://developers.google.com/youtube/analytics/) (by [Frank M](https://github.com/sgtfrankieboy))
* [YouTube Data API](https://developers.google.com/youtube/v3/) (by [Frank M](https://github.com/sgtfrankieboy/))
diff --git a/ws/ws-tests.ts b/ws/ws-tests.ts
new file mode 100644
index 0000000000..ec2bc431e0
--- /dev/null
+++ b/ws/ws-tests.ts
@@ -0,0 +1,53 @@
+///
+
+import WebSocket = require('ws');
+var WebSocketServer = WebSocket.Server;
+
+{
+ var ws = new WebSocket('ws://www.host.com/path');
+ ws.on('open', () => ws.send('something'));
+ ws.on('message', (data, flags) => {});
+}
+
+{
+ var ws = new WebSocket('ws://www.host.com/path');
+ ws.on('open', () => {
+ var array = new Float32Array(5);
+ for (var i = 0; i < array.length; ++i) array[i] = i / 2;
+ ws.send(array, {binary: true, mask: true});
+ });
+}
+
+{
+ var wss = new WebSocketServer({port: 8080});
+ wss.on('connection', (ws) => {
+ ws.on('message', (message) => console.log('received: %s', message));
+ ws.send('something');
+ });
+}
+
+{
+ var wss = new WebSocketServer({port: 8080});
+
+ function broadcast(data: any) {
+ for(var i in wss.clients)
+ wss.clients[i].send(data);
+ };
+}
+
+{
+ var wsc = new WebSocket('ws://echo.websocket.org/', {
+ protocolVersion: 8,
+ origin: 'http://websocket.org'
+ });
+
+ wsc.on('open', () => wsc.send(Date.now().toString(), {mask: true}));
+ wsc.on('close', () => console.log('disconnected'));
+
+ wsc.on('message', (data, flags) => {
+ console.log('Roundtrip time: ' + (Date.now() - parseInt(data)) + 'ms', flags);
+ setTimeout(() => {
+ wsc.send(Date.now().toString(), {mask: true});
+ }, 500);
+ });
+}
diff --git a/ws/ws.d.ts b/ws/ws.d.ts
new file mode 100644
index 0000000000..39d189b0c9
--- /dev/null
+++ b/ws/ws.d.ts
@@ -0,0 +1,133 @@
+// Type definitions for ws
+// Project: https://github.com/einaros/ws
+// Definitions by: Paul Loyd
+// Definitions: https://github.com/borisyankov/DefinitelyTyped
+
+///
+
+declare module "ws" {
+ import events = require('events');
+ import http = require('http');
+ import net = require('net');
+
+ class WebSocket extends events.EventEmitter {
+ static CONNECTING: number;
+ static OPEN: number;
+ static CLOSING: number;
+ static CLOSED: number;
+
+ bytesReceived: number;
+ readyState: number;
+ protocolVersion: string;
+ url: string;
+ supports: any;
+
+ CONNECTING: number;
+ OPEN: number;
+ CLOSING: number;
+ CLOSED: number;
+
+ onopen: (event: {target: WebSocket}) => void;
+ onerror: (err: Error) => void;
+ onclose: (event: {wasClean: boolean; code: number; reason: string; target: WebSocket}) => void;
+ onmessage: (event: {data: any; type: string; target: WebSocket}) => void;
+
+ constructor(address: string, options?: {
+ protocol?: string;
+ agent?: http.Agent;
+ headers?: {[key: string]: string};
+ protocolVersion?: any;
+ host?: string;
+ origin?: string;
+ pfx?: any;
+ key?: any;
+ passphrase?: string;
+ cert?: any;
+ ca?: any[];
+ ciphers?: string;
+ rejectUnauthorized?: boolean;
+ });
+
+ close(code?: number, data?: any): void;
+ pause(): void;
+ resume(): void;
+ ping(data?: any, options?: {mask?: boolean; binary?: boolean}, dontFail?: boolean): void;
+ pong(data?: any, options?: {mask?: boolean; binary?: boolean}, dontFail?: boolean): void;
+ send(data: any, cb?: (err: Error) => void): void;
+ send(data: any, options: {mask?: boolean; binary?: boolean}, cb?: (err: Error) => void): void;
+ stream(options: {mask?: boolean; binary?: boolean}, cb?: (err: Error, final: boolean) => void): void;
+ stream(cb?: (err: Error, final: boolean) => void): void;
+ terminate(): void;
+
+ // HTML5 WebSocket events
+ addEventListener(method: string, listener?: () => void): void;
+ addEventListener(method: 'message', cb?: (event: {data: any; type: string; target: WebSocket}) => void): void;
+ addEventListener(method: 'close', cb?: (event: {wasClean: boolean; code: number;
+ reason: string; target: WebSocket}) => void): void;
+ addEventListener(method: 'error', cb?: (err: Error) => void): void;
+ addEventListener(method: 'open', cb?: (event: {target: WebSocket}) => void): void;
+
+ // Events
+ on(event: string, listener: () => void): WebSocket;
+ on(event: 'error', cb: (err: Error) => void): WebSocket;
+ on(event: 'close', cb: (code: number, message: string) => void): WebSocket;
+ on(event: 'message', cb: (data: any, flags: {binary: boolean}) => void): WebSocket;
+ on(event: 'ping', cb: (data: any, flags: {binary: boolean}) => void): WebSocket;
+ on(event: 'pong', cb: (data: any, flags: {binary: boolean}) => void): WebSocket;
+ on(event: 'open', cb: () => void): WebSocket;
+ addListener(event: string, listener: () => void): WebSocket;
+ addListener(event: 'error', cb: (err: Error) => void): WebSocket;
+ addListener(event: 'close', cb: (code: number, message: string) => void): WebSocket;
+ addListener(event: 'message', cb: (data: any, flags: {binary: boolean}) => void): WebSocket;
+ addListener(event: 'ping', cb: (data: any, flags: {binary: boolean}) => void): WebSocket;
+ addListener(event: 'pong', cb: (data: any, flags: {binary: boolean}) => void): WebSocket;
+ addListener(event: 'open', cb: () => void): WebSocket;
+ }
+
+ module WebSocket {
+ export interface IServerOptions {
+ host?: string;
+ port?: number;
+ server?: http.Server;
+ verifyClient?: {
+ (info: {origin: string; secure: boolean; req: http.ClientRequest}): boolean;
+ (info: {origin: string; secure: boolean; req: http.ClientRequest},
+ callback: (res: boolean) => void): void;
+ };
+ handleProtocols?: any;
+ path?: string;
+ noServer?: boolean;
+ disableHixie?: boolean;
+ clientTracking?: boolean;
+ }
+
+ export class Server extends events.EventEmitter {
+ options: IServerOptions;
+ path: string;
+ clients: WebSocket[];
+
+ constructor(options?: IServerOptions, callback?: Function);
+
+ close(): void;
+ handleUpgrade(request: http.ClientRequest, socket: net.NodeSocket,
+ upgradeHead: NodeBuffer, callback: (client: WebSocket) => void): void;
+
+ // Events
+ on(event: string, listener: () => void): Server;
+ on(event: 'error', cb: (err: Error) => void): Server;
+ on(event: 'headers', cb: (headers: string[]) => void): Server;
+ on(event: 'connection', cb: (client: WebSocket) => void): Server;
+ addListener(event: string, listener: () => void): Server;
+ addListener(event: 'error', cb: (err: Error) => void): Server;
+ addListener(event: 'headers', cb: (headers: string[]) => void): Server;
+ addListener(event: 'connection', cb: (client: WebSocket) => void): Server;
+ }
+
+ export function createServer(options?: IServerOptions,
+ connectionListener?: (client: WebSocket) => void): Server;
+ export function connect(address: string, openListener?: Function): void;
+ export function createConnection(address: string, openListener?: Function): void;
+ }
+
+ export = WebSocket;
+}