Link Search Menu Expand Document Documentation Menu

JavaScript client

The OpenSearch JavaScript (JS) client provides a safer and easier way to interact with your OpenSearch cluster. Rather than using OpenSearch from the browser and potentially exposing your data to the public, you can build an OpenSearch client that takes care of sending requests to your cluster. For the client’s complete API documentation and additional examples, see the JS client API documentation.

The client contains a library of APIs that let you perform different operations on your cluster and return a standard response body. The example here demonstrates some basic operations like creating an index, adding documents, and searching your data.

You can use helper methods to simplify the use of complicated API tasks. For more information, see Helper methods. For more advanced index actions, see the opensearch-js guides in GitHub.

Installing the JavaScript client

The client requires Node.js 14 or later.

To add the client to your project, install it from npm:

npm install @opensearch-project/opensearch

To install a specific version of the client, run the following command:

npm install @opensearch-project/opensearch@<version>

If you prefer to add the client manually or only want to examine the source code, see opensearch-js on GitHub.

Then require the client:

const { Client } = require("@opensearch-project/opensearch");

Connecting to OpenSearch

To connect to the default OpenSearch host, create a client object with the address https://localhost:9200 if you are using the Security plugin:

var host = "localhost";
var protocol = "https";
var port = 9200;
var auth = "admin:<custom-admin-password>"; // For testing only. Don't store credentials in code.
var ca_certs_path = "/full/path/to/root-ca.pem";

// Optional client certificates if you don't want to use HTTP basic authentication.
// var client_cert_path = '/full/path/to/client.pem'
// var client_key_path = '/full/path/to/client-key.pem'

// Create a client with SSL/TLS enabled.
var { Client } = require("@opensearch-project/opensearch");
var fs = require("fs");
var client = new Client({
  node: protocol + "://" + auth + "@" + host + ":" + port,
  ssl: {
    ca: fs.readFileSync(ca_certs_path),
    // You can turn off certificate verification (rejectUnauthorized: false) if you're using 
    // self-signed certificates with a hostname mismatch.
    // cert: fs.readFileSync(client_cert_path),
    // key: fs.readFileSync(client_key_path)
  },
});

If you are not using the Security plugin, create a client object with the address http://localhost:9200:

var host = "localhost";
var protocol = "http";
var port = 9200;

// Create a client
var { Client } = require("@opensearch-project/opensearch");
var client = new Client({
  node: protocol + "://" + host + ":" + port
});

Authenticating with Amazon OpenSearch Service: AWS Signature Version 4

To sign requests using the AWS SDK for JavaScript V3, install the V3 credential provider package:

npm install @aws-sdk/credential-provider-node

To sign requests using the AWS SDK for JavaScript V2, install the V2 SDK:

npm install aws-sdk

The AWS SDK for JavaScript V2 reached end of support on September 8, 2025. For new applications, use the AWS SDK for JavaScript V3 examples in this section.

In the following examples, replace the endpoint with your domain or collection endpoint, which is listed on the domain’s or collection’s details page in the Amazon OpenSearch Service console.

Use the following code to authenticate with AWS V2 SDK:

const AWS = require('aws-sdk'); // V2 SDK.
const { Client } = require('@opensearch-project/opensearch');
const { AwsSigv4Signer } = require('@opensearch-project/opensearch/aws');

const client = new Client({
  ...AwsSigv4Signer({
    region: 'us-east-1',
    service: 'es',
    // Must return a Promise that resolves to an AWS.Credentials object.
    // This function acquires the credentials when the client starts and
    // when the credentials expire.
    // The client refreshes the credentials only when they expire, using
    // Credentials.refreshPromise when it is available.

    // Example with AWS SDK V2:
    getCredentials: () =>
      new Promise((resolve, reject) => {
        // Any other method to acquire a new Credentials object can be used.
        AWS.config.getCredentials((err, credentials) => {
          if (err) {
            reject(err);
          } else {
            resolve(credentials);
          }
        });
      }),
  }),
  node: 'https://search-<domain-name>-<id>.us-east-1.es.amazonaws.com', // OpenSearch domain endpoint
});

Use the following code to authenticate with the AWS V2 SDK for Amazon OpenSearch Serverless:

const AWS = require('aws-sdk'); // V2 SDK.
const { Client } = require('@opensearch-project/opensearch');
const { AwsSigv4Signer } = require('@opensearch-project/opensearch/aws');

const client = new Client({
  ...AwsSigv4Signer({
    region: 'us-east-1',
    service: 'aoss',
    // Must return a Promise that resolves to an AWS.Credentials object.
    // This function acquires the credentials when the client starts and
    // when the credentials expire.
    // The client refreshes the credentials only when they expire, using
    // Credentials.refreshPromise when it is available.

    // Example with AWS SDK V2:
    getCredentials: () =>
      new Promise((resolve, reject) => {
        // Any other method to acquire a new Credentials object can be used.
        AWS.config.getCredentials((err, credentials) => {
          if (err) {
            reject(err);
          } else {
            resolve(credentials);
          }
        });
      }),
  }),
  node: 'https://<collection-id>.us-east-1.aoss.amazonaws.com', // OpenSearch Serverless collection endpoint
});

Use the following code to authenticate with AWS V3 SDK:

const { defaultProvider } = require('@aws-sdk/credential-provider-node'); // V3 SDK.
const { Client } = require('@opensearch-project/opensearch');
// Use the aws-v3 import path with the AWS SDK for JavaScript V3. It lazy loads
// only the V3 credential providers.
const { AwsSigv4Signer } = require('@opensearch-project/opensearch/aws-v3');

const client = new Client({
  ...AwsSigv4Signer({
    region: 'us-east-1',
    service: 'es',  // 'aoss' for OpenSearch Serverless
    // Must return a Promise that resolves to a credentials object containing
    // accessKeyId, secretAccessKey, and, optionally, sessionToken and expiration.
    // This function acquires the credentials when the client starts and
    // when the credentials expire.
    // The client treats the credentials as expired if they are within
    // requestTimeout milliseconds of expiration (the default is 30,000).

    // Example with AWS SDK V3:
    getCredentials: () => {
      // Any other credential provider that returns such a Promise can be used.
      const credentialsProvider = defaultProvider();
      return credentialsProvider();
    },
  }),
  node: 'https://search-<domain-name>-<id>.us-east-1.es.amazonaws.com', // OpenSearch domain endpoint
  // node: 'https://<collection-id>.us-east-1.aoss.amazonaws.com' for an OpenSearch Serverless collection endpoint
});

Use the following code to authenticate with the AWS V3 SDK for Amazon OpenSearch Serverless:

const { defaultProvider } = require('@aws-sdk/credential-provider-node'); // V3 SDK.
const { Client } = require('@opensearch-project/opensearch');
// Use the aws-v3 import path with the AWS SDK for JavaScript V3. It lazy loads
// only the V3 credential providers.
const { AwsSigv4Signer } = require('@opensearch-project/opensearch/aws-v3');

const client = new Client({
  ...AwsSigv4Signer({
    region: 'us-east-1',
    service: 'aoss',
    // Must return a Promise that resolves to a credentials object containing
    // accessKeyId, secretAccessKey, and, optionally, sessionToken and expiration.
    // This function acquires the credentials when the client starts and
    // when the credentials expire.
    // The client treats the credentials as expired if they are within
    // requestTimeout milliseconds of expiration (the default is 30,000).

    // Example with AWS SDK V3:
    getCredentials: () => {
      // Any other credential provider that returns such a Promise can be used.
      const credentialsProvider = defaultProvider();
      return credentialsProvider();
    },
  }),
  node: 'https://<collection-id>.us-east-1.aoss.amazonaws.com', // OpenSearch Serverless collection endpoint
});

Amazon OpenSearch Serverless supports a subset of OpenSearch API operations and does not support the refresh parameter used in the examples on this page. For more information, see Supported operations and plugins in Amazon OpenSearch Serverless.

Authenticating from within an AWS Lambda function

Within an AWS Lambda function, objects declared outside the handler function retain their initialization. For more information, see Lambda Execution Environment. Thus, you must initialize the OpenSearch client outside of the handler function to ensure the reuse of the original connection in subsequent invocations. This promotes efficiency and eliminates the need to create a new connection each time.

Initializing the client within the handler function poses a potential risk of encountering a ConnectionError: getaddrinfo EMFILE error. This error occurs when multiple connections are created in subsequent invocations, exceeding the system’s file descriptor limit.

The following example AWS Lambda function code demonstrates the correct initialization of the OpenSearch client:

const { defaultProvider } = require('@aws-sdk/credential-provider-node'); // V3 SDK.
const { Client } = require('@opensearch-project/opensearch');
// Use the aws-v3 import path with the AWS SDK for JavaScript V3. It lazy loads
// only the V3 credential providers.
const { AwsSigv4Signer } = require('@opensearch-project/opensearch/aws-v3');

const client = new Client({
  ...AwsSigv4Signer({
    region: 'us-east-1',
    service: 'es',  // 'aoss' for OpenSearch Serverless
    // Must return a Promise that resolves to a credentials object containing
    // accessKeyId, secretAccessKey, and, optionally, sessionToken and expiration.
    // This function acquires the credentials when the client starts and
    // when the credentials expire.
    // The client treats the credentials as expired if they are within
    // requestTimeout milliseconds of expiration (the default is 30,000).

    // Example with AWS SDK V3:
    getCredentials: () => {
      // Any other credential provider that returns such a Promise can be used.
      const credentialsProvider = defaultProvider();
      return credentialsProvider();
    },
  }),
  node: 'https://search-<domain-name>-<id>.us-east-1.es.amazonaws.com', // OpenSearch domain endpoint
  // node: 'https://<collection-id>.us-east-1.aoss.amazonaws.com' for an OpenSearch Serverless collection endpoint
});

exports.handler = async (event, context) => {
  // Use the already initialized client
  const response = await client.indices.create({
    index: "students",
  });

  return response.body;
};

Creating an index

The following example creates an index with one primary shard and one replica. It explicitly maps the gradDate field as a date in the yyyy-MM-dd format. OpenSearch maps the other document fields dynamically when you index documents:

var index_name = "students";

var response = await client.indices.create({
  index: index_name,
  body: {
    settings: {
      index: {
        number_of_shards: 1,
        number_of_replicas: 1,
      },
    },
    mappings: {
      properties: {
        gradDate: { type: "date", format: "yyyy-MM-dd" },
      },
    },
  },
});

Indexing a document

Index a document into OpenSearch using the client’s index method:

var student = { firstName: "John", lastName: "Doe", gpa: 3.89, gradDate: "2022-05-15" };

var response = await client.index({
  index: index_name,
  id: "1",
  body: student,
  refresh: true,
});

Bulk indexing

Index multiple documents in one request using the client’s bulk method. The request body is an array in which each action is followed by the document that it applies to:

var response = await client.bulk({
  body: [
    { index: { _index: index_name, _id: "2" } },
    { firstName: "Paulo", lastName: "Santos", gpa: 3.93, gradDate: "2021-05-20" },
    { index: { _index: index_name, _id: "3" } },
    { firstName: "Shirley", lastName: "Rodriguez", gpa: 3.91, gradDate: "2019-05-10" },
  ],
  refresh: true,
});

To build the request body from an array, a stream, or an async generator, use the bulk helper.

Searching for documents

Search for all documents in an index using the client’s search method:

var response = await client.search({
  index: index_name,
  body: {
    query: {
      match_all: {},
    },
  },
});
response.body.hits.hits.forEach((hit) => console.log(hit._source));

Each item in response.body.hits.hits is a plain JavaScript object. The document ID is in the _id property, and the document fields are properties of the _source object:

response.body.hits.hits.forEach((hit) => {
  console.log(
    `ID: ${hit._id}, name: ${hit._source.firstName} ${hit._source.lastName}, GPA: ${hit._source.gpa}, graduation date: ${hit._source.gradDate}`
  );
});

Search using a range query:

var response = await client.search({
  index: index_name,
  body: {
    query: {
      range: {
        gradDate: {
          gte: "2019-01-01",
          lte: "2019-12-31",
        },
      },
    },
  },
});

Paginating results

To paginate results, use the from and size parameters. The following example sorts students by graduation date and retrieves the results two at a time. The first request returns the first page of results, and the second request returns the next page:

var response = await client.search({
  index: index_name,
  body: {
    from: 0,
    size: 2,
    sort: [{ gradDate: "asc" }],
  },
});
response.body.hits.hits.forEach((hit) => console.log(hit._source));

var nextPage = await client.search({
  index: index_name,
  body: {
    from: 2,
    size: 2,
    sort: [{ gradDate: "asc" }],
  },
});
nextPage.body.hits.hits.forEach((hit) => console.log(hit._source));

The from and size parameters work well for the first pages of results. To paginate through a large number of results, use point in time with search_after. For more information, see Paginate results.

Updating a document

Update a document using the client’s update method. The doc object contains only the fields to update:

var response = await client.update({
  index: index_name,
  id: "1",
  body: {
    doc: { gpa: 3.92 },
  },
});

Deleting a document

Delete a document using the client’s delete method:

var response = await client.delete({
  index: index_name,
  id: "3",
  refresh: true,
});

Deleting an index

Delete an index using the indices.delete() method:

var response = await client.indices.delete({
  index: index_name,
});

Sample program

This sample program combines the code from the preceding sections. It connects to a cluster that has the Security plugin enabled. To connect to a cluster without the Security plugin, change the lines marked with // Without security comments.

This sample program is for testing only. It specifies credentials in code. In production, load credentials from a secure location.

The following sample program creates a client, creates an index, indexes documents individually and in bulk, searches for documents, updates a document, deletes a document, and then deletes the index:

"use strict";

var host = "localhost";
var protocol = "https"; // Without security, use "http"
var port = 9200;
// Without security, remove the following line
var auth = "admin:<custom-admin-password>";
var ca_certs_path = "/full/path/to/root-ca.pem"; // Without security, remove this line

// Optional client certificates if you don't want to use HTTP basic authentication
// var client_cert_path = '/full/path/to/client.pem'
// var client_key_path = '/full/path/to/client-key.pem'

// Create a client with SSL/TLS enabled
var { Client } = require("@opensearch-project/opensearch");
var fs = require("fs"); // Without security, remove this line
var client = new Client({
  // Without security, use node: protocol + "://" + host + ":" + port,
  node: protocol + "://" + auth + "@" + host + ":" + port,
  ssl: { // Without security, remove the ssl block
    ca: fs.readFileSync(ca_certs_path),
    // You can turn off certificate verification (rejectUnauthorized: false) if you're using
    // self-signed certificates with a hostname mismatch.
    // cert: fs.readFileSync(client_cert_path),
    // key: fs.readFileSync(client_key_path)
  },
});

async function main() {
  // Create the index
  var index_name = "students";
  console.log("Creating index......");
  var response = await client.indices.create({
    index: index_name,
    body: {
      settings: {
        index: {
          number_of_shards: 1,
          number_of_replicas: 1,
        },
      },
      mappings: {
        properties: {
          gradDate: { type: "date", format: "yyyy-MM-dd" },
        },
      },
    },
  });
  console.log("Index created: " + response.body.index);

  // Index a document
  console.log("\nIndexing one student......");
  var student = { firstName: "John", lastName: "Doe", gpa: 3.89, gradDate: "2022-05-15" };
  response = await client.index({
    index: index_name,
    id: "1",
    body: student,
    refresh: true,
  });
  console.log("Result: " + response.body.result + ", id: " + response.body._id + ", version: " + response.body._version);

  // Bulk index documents
  console.log("\nIndexing many students......");
  response = await client.bulk({
    body: [
      { index: { _index: index_name, _id: "2" } },
      { firstName: "Paulo", lastName: "Santos", gpa: 3.93, gradDate: "2021-05-20" },
      { index: { _index: index_name, _id: "3" } },
      { firstName: "Shirley", lastName: "Rodriguez", gpa: 3.91, gradDate: "2019-05-10" },
    ],
    refresh: true,
  });
  console.log("Errors: " + response.body.errors);
  response.body.items.forEach((item) =>
    console.log("  " + item.index.result + " id: " + item.index._id));

  // Search for all students
  console.log("\nSearching for all students......");
  response = await client.search({
    index: index_name,
    body: {
      from: 0,
      size: 2,
      sort: [{ gradDate: "asc" }],
    },
  });
  console.log("Total hits: " + response.body.hits.total.value);
  console.log("Page 1:");
  response.body.hits.hits.forEach((hit) => console.log("  " + JSON.stringify(hit._source)));
  response = await client.search({
    index: index_name,
    body: {
      from: 2,
      size: 2,
      sort: [{ gradDate: "asc" }],
    },
  });
  console.log("Page 2:");
  response.body.hits.hits.forEach((hit) => console.log("  " + JSON.stringify(hit._source)));

  // Search for students who graduated in 2019
  console.log("\nSearching for students who graduated in 2019......");
  response = await client.search({
    index: index_name,
    body: {
      query: {
        range: {
          gradDate: {
            gte: "2019-01-01",
            lte: "2019-12-31",
          },
        },
      },
    },
  });
  console.log("Total hits: " + response.body.hits.total.value);
  response.body.hits.hits.forEach((hit) => console.log("  " + JSON.stringify(hit._source)));

  // Update a document
  console.log("\nUpdating a student's GPA......");
  response = await client.update({
    index: index_name,
    id: "1",
    body: {
      doc: { gpa: 3.92 },
    },
  });
  console.log("Result: " + response.body.result + ", version: " + response.body._version);

  // Get the updated document
  response = await client.get({
    index: index_name,
    id: "1",
  });
  console.log("Updated document: " + JSON.stringify(response.body._source));

  // Delete a document
  console.log("\nDeleting a student......");
  response = await client.delete({
    index: index_name,
    id: "3",
    refresh: true,
  });
  console.log("Result: " + response.body.result);

  // Delete the index
  console.log("\nDeleting the index......");
  response = await client.indices.delete({
    index: index_name,
  });
  console.log("Acknowledged: " + response.body.acknowledged);
}

main().catch(console.log);

The program produces the following output:

Creating index......
Index created: students

Indexing one student......
Result: created, id: 1, version: 1

Indexing many students......
Errors: false
  created id: 2
  created id: 3

Searching for all students......
Total hits: 3
Page 1:
  {"firstName":"Shirley","lastName":"Rodriguez","gpa":3.91,"gradDate":"2019-05-10"}
  {"firstName":"Paulo","lastName":"Santos","gpa":3.93,"gradDate":"2021-05-20"}
Page 2:
  {"firstName":"John","lastName":"Doe","gpa":3.89,"gradDate":"2022-05-15"}

Searching for students who graduated in 2019......
Total hits: 1
  {"firstName":"Shirley","lastName":"Rodriguez","gpa":3.91,"gradDate":"2019-05-10"}

Updating a student's GPA......
Result: updated, version: 2
Updated document: {"firstName":"John","lastName":"Doe","gpa":3.92,"gradDate":"2022-05-15"}

Deleting a student......
Result: deleted

Deleting the index......
Acknowledged: true

Circuit breaker

The memoryCircuitBreaker option can be used to prevent errors caused by a response payload being too large to fit into the heap memory available to the client.

The memoryCircuitBreaker object contains two fields:

  • enabled: A Boolean used to turn the circuit breaker on or off. Defaults to false.
  • maxPercentage: The threshold that determines whether the circuit breaker engages. Valid values are floats in the [0, 1] range that represent percentages in decimal form. Any value that exceeds that range will correct to 1.0.

The following example instantiates a client with the circuit breaker enabled and its threshold set to 80% of the available heap size limit:

var client = new Client({
  memoryCircuitBreaker: {
    enabled: true,
    maxPercentage: 0.8,
  },
});