The changelog below reflects new product development and updates.

August 29, 2024

💻 Developer Console

Head to console.anon.com to get started!

You can now connect your desktop users on web without installing the Link SDK! Use the new link url API to generate a secure url that takes your users to Anon Link. Once they finish connecting their account, they will be redirected back to your web app.

Check out the new Anon Link for Web guide to learn more.

Seamless appUserIdToken creation

The clientId parameter for the POST /org/appUserIdToken endpoint is now optional! This is possible because all organizations now automatically have a default Anon-hosted user pool and corresponding SDK Client.

Check out the API reference to learn more.

⚡ Improved Quickstart

We’ve revamped our examples to make it even easier to get started with Anon. Our Quickstart guide used to require configuration of five different environment variables. Now, all you need is an API Key to use our new examples — our simplified APIs handle the rest!

Check out the examples repo on Github!

July 30, 2024

This update focused on bug fixes for “hanging” when linking accounts for some integrations, e.g. Resy.

  • Fixed a memory leak that could occur with WKWebView and certain integrations
  • Migrated HTTP client to Combine to simplify multithreaded changes
  • Simplified internal SwiftUI view builders to make views more responsive

This update focused on bug fixes for “hanging” and false positive success messages when linking accounts for some integrations, e.g. Resy.

  • New logic for connection completion

Runtime SDK v0.6.0

This update adds a new feature for configuring your own proxy, or turning off proxying functionality altogether.

BYOP — “Bring Your Own” Proxy

In the past, developers using Anon automatically used our proxy network while utilizing our Runtime SDK.

With the latest SDK update, you now have the option to use Anon’s proxy or configure your own proxy with setupAnonBrowserWithContext by using the new proxy configuration property:

{
  /**
   * Proxy to be used for all requests. HTTP and SOCKS proxies are supported, for example `http://myproxy.com:3128` or
   * `socks5://myproxy.com:3128`. Short form `myproxy.com:3128` is considered an HTTP proxy.
   */
  server: string;

  /**
   * Optional comma-separated domains to bypass proxy, for example `".com, chromium.org, .domain.com"`.
   */
  bypass?: string;

  /**
   * Optional username to use if HTTP proxy requires authentication.
   */
  username?: string;

  /**
   * Optional password to use if HTTP proxy requires authentication.
   */
  password?: string;
};

Let’s say you want to use your own proxy.

Setup the browserContext as follows:

const { browserContext } = await setupAnonBrowserWithContext(
  client,
  account,
  { type: "local", 
	  input: {
		  proxy: { server: "coolproxy.com:80", username: "foo", password: "bar" } 
	  }
  },
);

To use an Anon proxy, set the following:

const { browserContext } = await setupAnonBrowserWithContext(
  client,
  account,
  { type: "local", 
	  input: {
		  proxy: { isAnonProxyEnabled: true } 
	  }
  },
);

The proxy property is a union of types, so it can also take the form

{ isAnonProxyEnabled: bool } 

Likewise, to turn off proxying altogether, set the field as { isAnonProxyEnabled: false }

const { browserContext } = await setupAnonBrowserWithContext(
  client,
  account,
  { type: "local", 
	  input: {
		  proxy: { isAnonProxyEnabled: false } 
	  }
  },
);

or omit the proxy field entirely

const { browserContext } = await setupAnonBrowserWithContext(
  client,
  account,
  { type: "local", input: {}},
);

Anon Chrome Extension Library v0.6.0

🎉 Runtime SDK support for Chrome

Currently, the Runtime SDK integrates with browser automation frameworks like Playwright, and allows you to run authenticated user sessions with scripts that automate actions.

With the Runtime SDK support for Chrome you can run authenticated user sessions directly in your normal Chrome web browser, and take actions on your user’s behalf manually.

You can get started with Runtime SDK for Chrome by installing the latest version of the Anon Chrome Extension Library.

Add the library to your extension’s package.json:

Add the initialization function to a background service worker:

background.ts
import { AnonRuntime } from "@anon/sdk-browser-extension";

// launch anon sdk
const anonRuntime = new AnonRuntime({
  client: {
    environment: "sandbox",
    authToken: "your API Key",
  },
});

anonRuntime.start();

Run an authenticated user session:

popup.tsx
import { AnonRuntime, AnonClient } from "@anon/sdk-browser-extension";

// create an API client
const anonClient = new AnonClient({
  environment: "sandbox",
  clientId: "your sdk client ID",
  authToken: "your API Key",
});

// list your authenticated user sessions
const sessions = await ANON_CLIENT.getSessions();

// pick one
const [session] = sessions.filter((session) => {
  return (
    session.appUser.id === "your users id" &&
    sesssion.app === "linkedin"
  );
});

// run it!
await AnonRuntime.run(session.id, {
  // enable proxying
  proxyEnabled: true,
  // create a new tab instead of overwriting the current tab
  createTab: true,
});

Check out a full extension code example here!

API

List Endpoints

We’ve added list endpoints for the following resources:

Head to our API reference to learn more!

July 24, 2024

Feature

🐦 Twitter Integration

You can now use Twitter user sessions with Anon. Check the integrations table for a full list of supported integrations.

Here is an example to make a post on Twitter with Anon:

const postTweet = async (page: Page, message: string): Promise<void> => {
  // Navigate to the Twitter compose page
  await page.goto("https://twitter.com/compose/post", {
    waitUntil: "networkidle",
  });

  // Wait for the compose modal to appear
  await page.waitForSelector('div[aria-label="Post text"]', {
    state: "visible",
    timeout: 10000,
  });

  // Type the message
  await page.fill('div[aria-label="Post text"]', message);

  // Wait for the "Post" button to become clickable
  await page.waitForSelector('div[data-testid="tweetButtonInline"]', {
    state: "visible",
  });

  // Click the "Post" button
  await page.click('div[data-testid="tweetButtonInline"]');

  // Wait for the success notification
  await page.waitForSelector('div[data-testid="toast"]', {
    state: "visible",
    timeout: 10000,
  });
};

const account = {
  // check out our list of supported apps here: https://docs.anon.com/docs/getting-started/overview
  // this should align with a session you uploaded with the web-link example
  app: "linkedin",
  // this is the "sub" field of your user's JWTs
  userId: APP_USER_ID,
};

const APP_USER_ID = ...
const ENV = ...
const API_KEY = ...

const client = new Client({
  environment: ENV,
  // create a server SdkClient and use its ApiKey
  // for testing, can alternately use an admin member's api key
  apiKey: API_KEY,
});


const { browserContext, browser } = await setupAnonBrowserWithContext(
  client,
  account,
  {
    type: "local",
    input: { headless: false, proxy: { isAnonProxyEnabled: true } },
  },
);

const result = await executeRuntimeScript({
  client,
  account,
  target: { browserContext },
  initialUrl: "https://twitter.com/",
  run: postTweet,
});

🚀 Launch of the Anon Actions Library

  • Providing easy-to-use automation scripts for popular websites
  • Integration with Anon SDK for secure access to user sessions
  • Example usage code for quick implementation
List of App Actions
LinkedIn
FeatureFunction Name
Create a postcreatePost
Get connectionsgetConnections
Follow a companyfollowCompanyPage
Send a messagesendMessage
Get user infogetUserInfo
Send connection requestsendConnectionRequest
Amazon
FeatureFunction Name
Get all ordersgetAllOrders
Search for an itemsearchItem
Instagram
FeatureFunction Name
Send a direct messagesendMessage
Why It’s Important

Anon Actions is a significant addition to the Anon ecosystem because it allows developers to easily run automated actions using the Anon SDK. This library streamlines the process of building AI-driven applications that interact with popular web platforms on behalf of users. By providing pre-built, ready-to-use actions for sites like LinkedIn and Amazon, Anon Actions reduces development time and complexity, enabling faster creation of sophisticated AI agents and automated workflows.

The importance of Anon Actions lies in its ability to bridge the gap between AI capabilities and real-world web interactions. It empowers developers to quickly implement complex web automation tasks without having to build everything from scratch. This opens up new possibilities for creating intelligent, interactive applications that can perform tasks across various web platforms seamlessly and securely, all while leveraging the power of the Anon SDK and user sessions.

July 2, 2024

Runtime SDK v0.5.0

Managed Browser Contexts

You no longer need to run headless browsers like Playwright or Puppeteer on your own infrastructure. Let Anon do the work!

To use this feature, modify the setupAnonBrowserWithContext argument contextOptions to use a new type enum called "managed".

  const { browserContext, browser } = await setupAnonBrowserWithContext(
    client,
    account,
    { type: "managed", input: { }, },
  );

  const page = browser.contexts()[0].pages()[0];

  await executeRuntimeScript({
    client,
    account,
    target: { page },
    initialUrl: "www.example.com",
    run,
  });

Cleanup Options

You can indicate whether or not you want to close your page or browser context when running executeRuntimeScript. This change enables you to control whether you’d like to execute different scripts on the same page or a new one.

To use the feature, you just need to specify the cleanupOptions when running executeRuntimeScript.

  const { browserContext, browser } = await setupAnonBrowserWithContext(
    client,
    account,
    { type: "managed", input: { }, },
  );

  const page = browser.contexts()[0].pages()[0];

  await executeRuntimeScript({
    client,
    account,
    target: { page: page },
    initialUrl: "www.example.com",
    cleanupOptions: { closePage: false, closeBrowserContext: false },
    run: run,
  });

React Native Support

You can now use the Link SDK with React Native for iOS apps! Check out our new documentation to learn more.

Bug Fixes

We’ve improved reliability & support for integrations on iOS and squashed bugs related to hanging logins and false positive success pages.

Hosted UserPools

Now you can create UserPools without the need for a JWKS URI from an external identity provider. Anon can host one for you! Learn how to create a new hosted UserPool in our documentation and API reference.

With a hosted UserPool, you can generate an appUserIdToken using our new [GET /org/appUserIdToken endpoint]((/reference/api/appuseridtoken/issue-a-new-appuseridtoken). Check out our documentation to learn more.

June 15, 2024

Features

Add Session Status and Session Deletion.

Session Status

You can now check the status of an user session. Example usage:

import { Client } from "@anon/sdk-typescript";

const client = new Client({...});
await client.getSessionStatus({ account: { ownerId: "<app_user_id>", domain: "<app_enum>" }});

The response will be { "status": SessionStatusEnum } where SessionStatusEnum is one of:

- "active": Session is valid and ready for automation.
- "revoked": Session is invalid and the user needs to log in again.
- "unknown": Unable to determine the session status.

Session Deletion

You can now delete a user session. Example usage:

import { Client } from "@anon/sdk-typescript";

const client = new Client({...});
await client.deleteSession({ account: { ownerId: "<app_user_id>", domain: "<app_enum>" }});

Check out more detailed usage examples in our SDK reference here.

Was this page helpful?