# Querying Users

The Query Users method allows you to search for users and see if they are online/offline. The example below shows how you can retrieve the details for 3 users in one API call:

<codetabs>

<codetabs-item value="kotlin" label="Kotlin">

```kotlin
// Search for users with id "john", "jack", or "jessie"
val request = QueryUsersRequest(
  filter = Filters.`in`("id", listOf("john", "jack", "jessie")),
  offset = 0,
  limit = 3,
)

client.queryUsers(request).enqueue { result ->
  if (result is Result.Success) {
    val users: List<User> = result.value
  } else {
    // Handle Result.Failure
  }
}
```

</codetabs-item>

<codetabs-item value="javascript" label="JavaScript">

```js
const response = await client.queryUsers({
  id: { $in: ["john", "jack", "jessie"] },
});
```

</codetabs-item>

<codetabs-item value="java" label="Java">

```java
// Search users with id "john", "jack", or "jessie"
FilterObject filter = Filters.in("id", Arrays.asList("john", "jack", "jessie"));
int offset = 0;
int limit = 3;
QueryUsersRequest request = new QueryUsersRequest(filter, offset, limit);

client.queryUsers(request).enqueue(result -> {
  if (result.isSuccess()) {
    List<User> users = result.data();
  } else {
    // Handle result.error()
  }
});
```

</codetabs-item>

<codetabs-item value="swift" label="Swift">

```swift
let controller = chatClient.userListController(
  query: .init(filter: .in(.id, values: ["john", "jack", "jessie"]))
)

controller.synchronize { error in
  if let error = error {
    // handle error
    print(error)
  } else {
    // access users
    print(controller.users)
  }
}
```

</codetabs-item>

<codetabs-item value="php" label="PHP">

```php
$response = $client->queryUsers([ 'id' => ['$in' => ['john', 'jack', 'jessie'] ] ]);
```

</codetabs-item>

<codetabs-item value="dart" label="Dart">

```dart
final _result = client.queryUsers(
 filter: Filter.in_(['john', 'jack', 'jessie']),
);
```

</codetabs-item>

<codetabs-item value="unreal" label="Unreal">

```cpp
Client->QueryUsers(
  FFilter::In(TEXT("id"), {TEXT("john"), TEXT("jack"), TEXT("jessie")}),
  {},   // Sort
  true,  // Presence
  {},   // Pagination options
  [](const TArray<FUserRef>& Users)
  {
    // Do something with Users
  });
```

</codetabs-item>

<codetabs-item value="csharp" label="C#">

```csharp
var resp = await userClient.QueryAsync(QueryUserOptions.Default.WithFilter(new Dictionary<string, object>
{
  { "id", new Dictionary<string, object> { { "$in", new[]{ "john", "jack", "jassie" } } } },
}));
```

</codetabs-item>

<codetabs-item value="python" label="Python">

```python
client.query_users({"id": {"$in": ["Jack", "Joe", "Jesie"]}})
```

</codetabs-item>

<codetabs-item value="unity" label="Unity">

```csharp
var filters = new IFieldFilterRule[]
{
  UserFilter.Id.In("user-1", "user-2", "user-3")
};
// Returns collection of IStreamUser
var users = await Client.QueryUsersAsync(filters);
```

</codetabs-item>

<codetabs-item value="ruby" label="Ruby">

```ruby
# require 'stream-chat'

client.query_users({"id": {"$in": ["Jack", "Joe", "Jesie"]}})
```

</codetabs-item>

</codetabs>

<codetabs>

<codetabs-item value="kotlin" label="Kotlin">

```kotlin
val request = QueryUsersRequest(
  filter = Filters.`in`("id", listOf("jessica")),
  querySort = QuerySortByField.descByName("last_active"),
  offset = 0,
  limit = 1,
  presence = true,
)
client.queryUsers(request).enqueue { /* ... */ }
```

</codetabs-item>

<codetabs-item value="javascript" label="JavaScript">

```js
const response = await client.queryUsers(
  { id: { $in: ["jessica"] } },
  { last_active: -1 },
  { presence: true },
);
```

</codetabs-item>

<codetabs-item value="swift" label="Swift">

```swift
let controller = chatClient.userListController(
  query: .init(
    filter: .in(.id, values: ["john", "jack", "jessie"]),
    sort: [.init(key: .lastActivityAt, isAscending: false)]
  )
)

controller.synchronize { error in
  if let error = error {
    // handle error
    print(error)
  } else {
    // access users
    print(controller.users)
  }
}

// load more if needed
controller.loadNextUsers(limit: 10) { error in
  // handle error / access users
}
```

</codetabs-item>

<codetabs-item value="php" label="PHP">

```php
$response = $client->queryUsers(
[
 'id' => ['$in' => ['john', 'jack', 'jessie'] ],
 'last_active' => '2019-11-05T21:35:24.397995Z',
]);
```

</codetabs-item>

<codetabs-item value="dart" label="Dart">

```dart
final _result = client.queryUsers(
 filter: Filter.in_(['john', 'jack', 'jessie']),
 sort: [SortOption('last_active')],
 pagination: PaginationParams(
  offset: 0,
  limit: 20,
 ),
);
```

</codetabs-item>

<codetabs-item value="unreal" label="Unreal">

```cpp
Client->QueryUsers(
  FFilter::In(TEXT("id"), {TEXT("john"), TEXT("jack"), TEXT("jessie")}),
  {FUserSortOption{EUserSortField::LastActive}},
  true,     // bPresence
  {{20, 0}},  // Pagination options
  [](const TArray<FUserRef>& Users)
  {
    // Do something with Users
  });
```

</codetabs-item>

<codetabs-item value="csharp" label="C#">

```csharp
var query = QueryUserOptions.Default.WithFilter(new Dictionary<string, object>
{
  { "id", new Dictionary<string, object> { { "$in", new[]{"jessica"} } } },
});
query.Presence = true;

var resp = await userClient.QueryAsync(query);
```

</codetabs-item>

<codetabs-item value="python" label="Python">

```python
client.query_users({"id": {"$eq": "Jessica"}}, { "last_active": -1})
```

</codetabs-item>

<codetabs-item value="unity" label="Unity">

```csharp
var lastWeek = DateTime.Now.AddDays(-7);
var filters = new IFieldFilterRule[]
{
  UserFilter.CreatedAt.GreaterThanOrEquals(lastWeek)
};

// Order results by one or multiple fields e.g
var sort = UsersSort.OrderByDescending(UserSortField.CreatedAt);

var limit = 30; // How many records per page
var offset = 0; // How many records to skip e.g. offset = 30 -> page 2, offset = 60 -> page 3, etc.

// Returns collection of IStreamUser
var users = await Client.QueryUsersAsync(filters, sort, offset, limit);
```

</codetabs-item>

<codetabs-item value="ruby" label="Ruby">

```ruby
client.query_users({"id": {"$eq": "Jessica"}}, { "last_active": -1})
```

</codetabs-item>

</codetabs>

Another option is to query for `banned` users. This can be done with the following code snippet:

<codetabs>

<codetabs-item value="kotlin" label="Kotlin">

```kotlin
val request = QueryUsersRequest(
  filter = Filters.eq("banned", true),
  offset = 0,
  limit = 10,
)

client.queryUsers(request).enqueue { /* ... */ }
```

</codetabs-item>

<codetabs-item value="javascript" label="JavaScript">

```js
const banned = await client.queryUsers({ id: "jessica", banned: true });
```

</codetabs-item>

<codetabs-item value="php" label="PHP">

```php
$banned = $client->queryUsers(
[
 'id' => 'bob-1',
 'banned' => true,
]);
```

</codetabs-item>

<codetabs-item value="swift" label="Swift">

```swift
let controller = chatClient.userListController(
  query: .init(
    filter: .equal(.isBanned, to: true),
    sort: [.init(key: .lastActivityAt, isAscending: false)]
  )
)

controller.synchronize { error in
  if let error = error {
    // handle error
    print(error)
  } else {
    // access users
    print(controller.users)
  }
}
```

</codetabs-item>

<codetabs-item value="java" label="Java">

```java
FilterObject filter = Filters.eq("banned", true);
int offset = 0;
int limit = 10;
QueryUsersRequest request = new QueryUsersRequest(filter, offset, limit);

client.queryUsers(request).enqueue(result -> { /* ... */ });
```

</codetabs-item>

<codetabs-item value="dart" label="Dart">

```dart
final _result = client.queryUsers(
 filter: Filter.and(
  Filter.equal('id', 'jessie'),
  Filter.equal('banned', true),
 ),
 sort: [SortOption('last_active')],
 pagination: PaginationParams(
  offset: 0,
  limit: 20,
 ),
);
```

</codetabs-item>

<codetabs-item value="unreal" label="Unreal">

```cpp
Client->QueryUsers(
  FFilter::And({
    FFilter::Equal(TEXT("id"), TEXT("jessie")),
    FFilter::Equal(TEXT("banned"), true),
  }),
  {FUserSortOption{EUserSortField::LastActive}},
  true,  // Presence
  {},   // Pagination options
  [](const TArray<FUserRef>& Users)
  {
    // Do something with Users
  });
```

</codetabs-item>

<codetabs-item value="csharp" label="C#">

```csharp
var resp = await userClient.QueryAsync(QueryUserOptions.Default.WithFilter(new Dictionary<string, object>
{
  { "id", new Dictionary<string, object> { { "$in", new[]{ "john" } } } },
  { "banned": true },
}));
```

</codetabs-item>

<codetabs-item value="python" label="Python">

```python
client.query_users({"id": {"$eq": "Jessica"}, "banned": True})
```

</codetabs-item>

<codetabs-item value="unity" label="Unity">

```csharp
// Returns collection of StreamUserBanInfo
var usersBanInfo = await Client.QueryBannedUsersAsync(new StreamQueryBannedUsersRequest
{
  CreatedAtAfter = null, // Optional Banned after this date
  CreatedAtAfterOrEqual = null, // Optional Banned after or equal this date
  CreatedAtBefore = null, // Optional Banned before this date
  CreatedAtBeforeOrEqual = null, // Optional Banned before or equal this date
  FilterConditions = null, // Optional filter
  Limit = 30,
  Offset = 60,
  Sort = new List<StreamSortParam> // Optional sort
  {
    new StreamSortParam
    {
      Field = "created_at",
      Direction = -1,
    }
  },
});

foreach (var banInfo in usersBanInfo)
{
  Debug.Log(banInfo.User); // Which user
  Debug.Log(banInfo.Channel); // From which channel
  Debug.Log(banInfo.Reason); // Reason why banned
  Debug.Log(banInfo.Expires); // Optional expiry date
  Debug.Log(banInfo.Shadow); // Is this a shadow ban
  Debug.Log(banInfo.BannedBy); // Who created a ban
  Debug.Log(banInfo.CreatedAt); // Date when banned
}
```

</codetabs-item>

<codetabs-item value="ruby" label="Ruby">

```ruby
client.query_users({"id": {"$eq": "Jessica"}, "banned": true})
```

</codetabs-item>

</codetabs>

An object with an array of users will be returned.

<admonition type="info">

Please be aware that this query will return users banned across the entire app, not at a channel level.

</admonition>

<admonition type="warning">

All filters use a Mongoose style syntax; however, we do not run MongoDB on the backend, so you can only use a subset of queries that are normally available within Mongoose. The supported queries are described below.

</admonition>

You can filter and sort on the custom fields you've set for your user, the user id, and when the user was last active.

### Supported queries

The options for the `queryUser` method are `include_deactivated_users` , `presence` , `limit` , and `offset` . If `presence` is `true` this makes sure you receive the `user.presence.changed` event when a user goes online or offline.

| name                      | type                       | description                                                                                                                                                                                    | default                      | optional |
| ------------------------- | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- | -------- |
| filter_conditions         | objects                    | Conditions to use to filter the users                                                                                                                                                          | -                            |          |
| presence                  | boolean                    | Get updates when the user goes offline/online                                                                                                                                                  | true                         | ✓        |
| sort                      | object or array of objects | The sorting used for the users matching the filters. Sorting is based on field and direction, and multiple sorting options can be provided. Direction can be ascending (1) or descending (-1). | [{created_at: -1}, {id: -1}] | ✓        |
| limit                     | integer                    | Number of users to return                                                                                                                                                                      | 30                           | ✓        |
| offset                    | integer                    | Offset for pagination                                                                                                                                                                          | 0                            | ✓        |
| id_gt                     | string                     | ID-based pagination. Return IDs greater than this ID. If this is not empty, the default sort order will be [{id: -1}].                                                                         | -                            | ✓        |
| id_gte                    | string                     | ID-based pagination. Return IDs greater than or equal to this ID. If this is not empty, the default sort order will be [{id: -1}].                                                             | -                            | ✓        |
| id_lt                     | string                     | ID-based pagination. Return IDs less than this ID. If this is not empty, the default sort order will be [{id: -1}].                                                                            | -                            | ✓        |
| id_lte                    | string                     | ID-based pagination. Return IDs less than or equal to this ID. If this is not empty, the default sort order will be [{id: -1}].                                                                | -                            | ✓        |
| include_deactivated_users | boolean                    | Include deactivated users in the response                                                                                                                                                      | -                            | ✓        |

<admonition type="info">

You can subscribe to presence status of at most 30 users using this method.

</admonition>

<admonition type="info">

Note - The offset limit is set to 1000.

</admonition>

Filter conditions

| Name          | Type                                              | Description                        | allowed operators                             |
| ------------- | ------------------------------------------------- | ---------------------------------- | --------------------------------------------- |
| id            | string                                            | ID of the user                     | $eq, $gt, $gte, $lt, $lte, $in, $autocomplete |
| role          | string                                            | role of the user                   | $eq, $gt, $gte, $lt, $lte, $in                |
| banned        | boolean                                           | users that have been banned        | $eq                                           |
| shadow_banned | boolean                                           | users that have been shadow banned | $eq                                           |
| created_at    | string, must be formatted as an RFC3339 timestamp | created time of the user           | $eq, $gt, $gte, $lt, $lte, $in                |
| updated_at    | string, must be formatted as an RFC3339 timestamp | updated time of the user           | $eq, $gt, $gte, $lt, $lte, $in                |
| last_active   | string, must be formatted as an RFC3339 timestamp | time when the user was last active | $eq, $gt, $gte, $lt, $lte, $in, $exists       |
| teams         | string                                            | teams that the user belongs to     | $eq, $contains                                |
| name          | string                                            | name property of the user          | $eq, $autocomplete                            |
| username      | string                                            | username property of the user      | $eq, $autocomplete                            |

### Querying Using the $autocomplete Operator

You can autocomplete the results of your user query by username and/or ID.

#### 1. By Name

If you want to return all users whose field `'name'` has a value that includes `'ro'` , you could do so with the following:

<codetabs>

<codetabs-item value="kotlin" label="Kotlin">

```kotlin
val request = QueryUsersRequest(
  filter = Filters.autocomplete("name", "ro"),
  offset = 0,
  limit = 10,
)

client.queryUsers(request).enqueue { /* ... */ }
```

</codetabs-item>

<codetabs-item value="javascript" label="JavaScript">

```js
const response = await serverClient.queryUsers({
  name: { $autocomplete: "ro" },
});
```

</codetabs-item>

<codetabs-item value="php" label="PHP">

```php
$response = $client->queryUsers(
[
 'name' => ['$autocomplete' => 'ro']
]);
```

</codetabs-item>

<codetabs-item value="swift" label="Swift">

```swift
let controller = chatClient.userListController(
  query: .init(filter: .autocomplete(.name, text: "ro"))
)

controller.synchronize { error in
  if let error = error {
    // handle error
    print(error)
  } else {
    // access users
    print(controller.users)
  }
}
```

</codetabs-item>

<codetabs-item value="java" label="Java">

```java
FilterObject filter = Filters.autocomplete("name", "ro");
int offset = 0;
int limit = 10;
QueryUsersRequest request = new QueryUsersRequest(filter, offset, limit);

client.queryUsers(request).enqueue(result -> { /* ... */ });
```

</codetabs-item>

<codetabs-item value="dart" label="Dart">

```dart
final _result = client.queryUsers(
 filter: Filter.autoComplete('name', 'ro'),
);
```

</codetabs-item>

<codetabs-item value="unreal" label="Unreal">

```cpp
Client->QueryUsers(
  FFilter::Autocomplete(TEXT("name"), TEXT("ro")),
  {},   // Sort
  true,  // Presence
  {},   // Pagination options
  [](const TArray<FUserRef>& Users)
  {
    // Do something with Users
  });
```

</codetabs-item>

<codetabs-item value="csharp" label="C#">

```csharp
var resp = await _userClient.QueryAsync(QueryUserOptions.Default.WithFilter(new Dictionary<string, object>
{
  { "name", new Dictionary<string, object> { { "$autocomplete", "ro" } } },
}));
```

</codetabs-item>

<codetabs-item value="python" label="Python">

```python
client.query_users({"name": {"$autocomplete": "ro"}})
```

</codetabs-item>

<codetabs-item value="ruby" label="Ruby">

```ruby
client.query_users({"name": {"$autocomplete": "ro"}})
```

</codetabs-item>

<codetabs-item value="unity" label="Unity">

```csharp
var filters = new IFieldFilterRule[]
{
  UserFilter.Name.Autocomplete("Ro")
};
// Returns collection of IStreamUser
var users = await Client.QueryUsersAsync(filters);
```

</codetabs-item>

</codetabs>

This would return an array of any matching users, such as:

<codetabs>

<codetabs-item value="json" label="JSON">

```json
[
  {
    "id": "userID",
    "name": "Curiosity Rover"
  },
  {
    "id": "userID2",
    "name": "Roxy"
  },
  {
    "id": "userID3",
    "name": "Roxanne"
  }
]
```

</codetabs-item>

</codetabs>

#### 2. By ID

<codetabs>

<codetabs-item value="kotlin" label="Kotlin">

```kotlin
val request = QueryUsersRequest(
  filter = Filters.autocomplete("id", "USER_ID"),
  offset = 0,
  limit = 10,
)

client.queryUsers(request).enqueue { /* ... */ }
```

</codetabs-item>

<codetabs-item value="javascript" label="JavaScript">

```js
const response = await client.queryUsers({ id: { $autocomplete: "USER_ID" } });
```

</codetabs-item>

<codetabs-item value="php" label="PHP">

```php
$response = $client->queryUsers(
[
 'id' => ['$autocomplete' => 'user-id']
]);
```

</codetabs-item>

<codetabs-item value="swift" label="Swift">

```swift
let controller = chatClient.userListController(
  query: .init(filter: .autocomplete(.id, text: "ro"))
)

controller.synchronize { error in
  if let error = error {
    // handle error
    print(error)
  } else {
    // access users
    print(controller.users)
  }
}
```

</codetabs-item>

<codetabs-item value="java" label="Java">

```java
FilterObject filter = Filters.autocomplete("id", "USER_ID");
int offset = 0;
int limit = 10;
QueryUsersRequest request = new QueryUsersRequest(filter, offset, limit);

client.queryUsers(request).enqueue(result -> { /* ... */ });
```

</codetabs-item>

<codetabs-item value="dart" label="Dart">

```dart
final _result = client.queryUsers(
 filter: Filter.autocomplete('id', 'userid'),
);
```

</codetabs-item>

<codetabs-item value="unreal" label="Unreal">

```cpp
Client->QueryUsers(
  FFilter::Autocomplete(TEXT("id"), TEXT("userid")),
  {},   // Sort
  true,  // Presence
  {},   // Pagination options
  [](const TArray<FUserRef>& Users)
  {
    // Do something with Users
  });
```

</codetabs-item>

<codetabs-item value="csharp" label="C#">

```csharp
var resp = await _userClient.QueryAsync(QueryUserOptions.Default.WithFilter(new Dictionary<string, object>
{
  { "name", new Dictionary<string, object> { { "$autocomplete", userId } } },
}));
```

</codetabs-item>

<codetabs-item value="python" label="Python">

```python
client.query_users({"name": {"$autocomplete": user_id}})
```

</codetabs-item>

<codetabs-item value="ruby" label="Ruby">

```ruby
client.query_users({"name": {"$autocomplete": user_id}})
```

</codetabs-item>

<codetabs-item value="unity" label="Unity">

```csharp
var filters = new IFieldFilterRule[]
{
  // Return all users with Id starting with `Ro` like: Roxy, Roxanne, Rover
  UserFilter.Name.Autocomplete("Ro")
};
// Returns collection of IStreamUser
var users = await Client.QueryUsersAsync(filters);
```

</codetabs-item>

</codetabs>

### Querying users that have never connected

You can use the `last_active` field in combination with the `$exists` operator to query users that have never connected. You can also use `"$exists": true` to filter users that have connected at least once.

<codetabs>

<codetabs-item value="javascript" label="JavaScript">

```js
const response = await client.queryUsers({
  id: { $in: [activeUser, neverActiveUser] },
  last_active: { $exists: false },
});
```

</codetabs-item>

<codetabs-item value="python" label="Python">

```python
users = client.query_users({"last_active": {"$exists": false}})
```

</codetabs-item>

</codetabs>

---

This page was last updated at 2025-08-15T14:14:51.008Z.

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/node/query_users/](https://getstream.io/chat/docs/node/query_users/).