# Exporting Data

## Exporting Channels

This method allows you to request an export of one or many channels and download all messages and metadata. Channel exports are created asynchronously, you can use the `Task ID` returned by the APIs to keep track of the status and to download the final result when it is ready.

The data created by the export is following the same format as the regular APIs and is JSON encoded. By default the entire history is included in the export (excluding truncated messages), but you may optionally request the export to include only the messages in a specific interval using the `messages_since` and `messages_until` parameters.

### Requesting a channel export

Following code example presents basic usecase of exporting channels. By default truncated messages or soft deleted channels are excluded from export. But you can include them by setting the options `include_truncated_messages` and `include_soft_deleted_channels` as true.

<codetabs>

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

```js
//Export one channel
const response = await serverClient.exportChannel(
  {
    type: "livestream",
    id: "white-room",
    messages_since: "2020-11-10T09:30:00.000Z",
    messages_until: "2020-11-10T11:30:00.000Z",
  },
  {
    include_truncated_messages: true,
    include_soft_deleted_channels: true,
  },
);

const taskID = response.task_id;

//Export multiple channels
const response = await serverClient.exportChannels(
  [
    {
      type: "livestream",
      id: "white-room",
      messages_since: "2020-11-10T09:30:00.000Z",
      messages_until: "2020-11-10T11:30:00.000Z",
    },
    {
      type: "livestream",
      id: "white-room2",
    },
  ],
  {
    include_truncated_messages: true,
    include_soft_deleted_channels: true,
  },
);
const taskID = response.task_id;
```

</codetabs-item>

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

```python
response = client.export_channel(
  "livestream",
  "white-room",
  messages_since="2020-11-10T09:30:00.000Z",
  messages_until="2020-11-10T11:30:00.000Z",
  include_truncated_messages=True,
  include_soft_deleted_channels=True,
 )


task_id = response["task_id"]

# Export multiple channels
response = client.export_channels(
  [{"type": "livestream",
   "id": "white-room", },
   {"type": "livestream",
   "id": "white-room2", }]
)

task_id = response["task_id"]
```

</codetabs-item>

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

```ruby
# require 'stream-chat'

channel_ids = client.query_channels({}, limit:, offset:)['channels'].pluck('channel').pluck('id')
 channel_map = channel_ids.map { |e| [[:type, 'messaging'], [:id, e]].to_h }
 options = { include_truncated_messages: true }
 response = client.export_channels(*channel_map, **options)
```

</codetabs-item>

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

```php
$response = $client->exportChannel([
  'type' => 'livestream',
  'id' => 'white-room',
  'messages_since' => '2020-11-10T09:30:00.000Z',
  'messages_until' => '2020-11-10T11:30:00.000Z'
  ],
  ['include_truncated_messages' => true]
)

$taskId = $response['task_id']
```

</codetabs-item>

<codetabs-item value="go" label="Go">

```go
since := time.Date(2020, time.November, 10, 9, 30, 0, 0, time.UTC)
until := time.Date(2020, time.November, 10, 11, 30, 0, 0, time.UTC)
opts := &ExportChannelOptions{IncludeTruncatedMessages: &includeTruncated}

expChannels := []*ExportableChannel{
	{Type: "livestream", ID: "white-room", MessagesSince: &since, MessagesUntil: &until},
}

response, err := c.ExportChannels(ctx, expChannels, opts)

taskId := response.TaskID
```

</codetabs-item>

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

```csharp
var response = await channelClient.ExportChannelsAsync(new ExportChannelRequest
{
  Channels = new[] { new ExportChannelItem
  {
    Id = "white-room",
    Type = "livestream",
    MessagesSince = new DateTimeOffset(2020, 11, 10, 9, 30, 0, TimeSpan.Zero),
    MessagesUntil = new DateTimeOffset(2020, 11, 10, 11, 30, 0, TimeSpan.Zero),
  }},
  IncludeTruncatedMessages = true,
});

var taskId = response.TaskId;
```

</codetabs-item>

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

```java
Channel.export()
  .channel(
    ChannelExportRequestObject.builder()
      .type("channel-type")
      .id("channel-id")
      .build())
  .request();
```

</codetabs-item>

</codetabs>

<admonition type="info">

Up to 25 channels can be exported with a single export request.

</admonition>

you can use v2 version of the channel export by adding `version:"v2"` in the request body which will use the new export for channels where each entity of the export would be exported as line separated JSON.

<codetabs>

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

```js
const response = await serverClient.exportChannel(
  {
    type: "livestream",
    id: "white-room",
    messages_since: "2020-11-10T09:30:00.000Z",
    messages_until: "2020-11-10T11:30:00.000Z",
  },
  {
    version: "v2",
  },
);
```

</codetabs-item>

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

```python
response = client.export_channel(
 "livestream",
 "white-room",
 messages_since="2020-11-10T09:30:00.000Z",
 messages_until="2020-11-10T11:30:00.000Z",
 version="v2",
)
```

</codetabs-item>

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

```ruby
options = { version: 'v2' }
resp = client.export_channels({
                type: 'livestream',
                id: 'white-room',
                messages_since: '2020-11-10T09:30:00.000Z',
                messages_until: '2020-11-10T11:30:00.000Z'
                },
                **options)
```

</codetabs-item>

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

```php
$response = $client->exportChannel([
  'type' => 'livestream',
  'id' => 'white-room',
  'messages_since' => '2020-11-10T09:30:00.000Z',
  'messages_until' => '2020-11-10T11:30:00.000Z'
  ],
  ['version' => 'v2']
)
```

</codetabs-item>

<codetabs-item value="go" label="Go">

```go
since := time.Date(2020, time.November, 10, 9, 30, 0, 0, time.UTC)
until := time.Date(2020, time.November, 10, 11, 30, 0, 0, time.UTC)
opts := &ExportChannelOptions{Version: "v2"}

expChannels := []*ExportableChannel{
	{Type: "livestream", ID: "white-room", MessagesSince: &since, MessagesUntil: &until},
}

response, err := c.ExportChannels(ctx, expChannels, opts)
```

</codetabs-item>

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

```csharp
var response = await channelClient.ExportChannelsAsync(new ExportChannelRequest
{
  Channels = new[] { new ExportChannelItem
  {
    Id = "white-room",
    Type = "livestream",
    MessagesSince = new DateTimeOffset(2020, 11, 10, 9, 30, 0, TimeSpan.Zero),
    MessagesUntil = new DateTimeOffset(2020, 11, 10, 11, 30, 0, TimeSpan.Zero),
  }},
  Version = "v2",
});
```

</codetabs-item>

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

```java
Channel.export()
  .channel(
    ChannelExportRequestObject.builder()
      .type("channel-type")
      .id("channel-id")
      .build())
  .version("v2")
  .request();
```

</codetabs-item>

</codetabs>

### Retrieving the status of the export

You can check the status of an export request using the task ID returned when the task was created. The result of the task contains the URL to the JSON file.

<admonition type="info">

The URL to the export file has an expiration of 24-hours. The link is generated every time you request the export status. The export will be available for 60 days.

</admonition>

<codetabs>

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

```js
const response = await serverClient.getExportChannelStatus(taskId);

console.log(response.status); // the status for this task
console.log(response.result); // the result object, only present if the task is completed
console.log(response.result.url); // the link to the JSON export
console.log(response.error); // if not null the description of the task error
```

</codetabs-item>

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

```python
response = client.get_export_channel_status(task_id)

print(response["status"]);     # the status for this task
print(response["result"]);     # the result object, only present if the task is completed
print(response["result"]["url"]);  # the link to the JSON export
print(response["error"]);      # if not null the description of the task error
```

</codetabs-item>

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

```ruby
response = client.get_export_channel_status(task_id)

puts response['status']     # the status for this task
puts response['result']     # the result object, only present if the task is completed
puts response['result']['url']  # the link to the JSON export
puts response['error']      # if not null the description of the task error
```

</codetabs-item>

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

```php
$response = $client->getExportChannelStatus($taskId)

echo $response['status']     // the status for this task
echo $response['result']     // the result object, only present if the task is completed
echo $response['result']['url']  // the link to the JSON export
echo $response['error']      // if not null the description of the task error
```

</codetabs-item>

<codetabs-item value="go" label="Go">

```go
task, err := c.GetExportChannelsTask(ctx, response.TaskID)

fmt.Println(task.Status)     // the status for this task
fmt.Println(task.Result)     // the result object, only present if the task is completed
fmt.Println(task.Result["url"])  // the link to the JSON export
fmt.Println(task.Error)      // if not null the description of the task error
```

</codetabs-item>

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

```csharp
var response = await channelClient.GetExportChannelsStatusAsync(taskId);

Console.WriteLine(response.Status);   // the status for this task
Console.WriteLine(response.Result);   // the result object, only present if the task is completed
Console.WriteLine(response.Result.Url;  // the link to the JSON export
Console.WriteLine(response.Error);    // if not null the description of the task error
```

</codetabs-item>

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

```java
var response = Channel.exportStatus(taskId).request();

System.out.println(response.getStatus());     // the status for this task
System.out.println(response.getResult());     // the result object, only present if the task is completed
System.out.println(response.getResult().getUrl()); // the link to the JSON export
System.out.println(response.getError());      // if not null the description of the task error
```

</codetabs-item>

</codetabs>

Timestamps will be returned in this format: "2021-02-17T08:17:49.745857Z" and are in UTC.

## Exporting Users (async)

The export users endpoint follows the same pattern as the export channels endpoint. It can export up to 25 users at a time asynchronsously. The following data will be exported:

- Users
- Messages
- Reactions
- Calls
- Custom data

The format of the export is the same as the `v2` format for exporting channels, line separated JSON.

### Requesting a users export

Following code example presents basic usecase of exporting users.

<codetabs>

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

```js
const response = await serverClient.exportUsers(
  user_ids: [user1.id, user2.id],
);
const taskID = response.task_id;
```

</codetabs-item>

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

```csharp
var exportResponse = await _userClient.ExportUsersAsync(new[] { "user-id-1", "user-id-2" });
var taskId = exportResponse.TaskId;
```

</codetabs-item>

</codetabs>

<admonition type="info">

Up to 25 users can be exported with a single export request.

</admonition>

### Retrieving the status of the export

You can check the status of an export request using the task ID returned when the task was created. The result of the task contains the URL to the JSON file.

<admonition type="info">

The URL to the export file has an expiration of 24-hours. The link is generated every time you request the export status. The export will be available for 60 days.

</admonition>

<codetabs>

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

```js
response = await serverClient.getTask(response["task_id"]);

if (response["status"] === "completed") {
  // success!
  console.log(response["result"]["url"]);
}
```

</codetabs-item>

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

```python
response = client.get_task(response["task_id"])

if response['status'] == 'completed':
  # success!
  print(response['result']['url'])
```

</codetabs-item>

<codetabs-item value="go" label="Go">

```go
resp, err := client.GetTask(taskID)
if err != nil {
  return err
}

if resp.Status == "completed" {
  // success!
  fmt.Println(resp.Result["url"])
}
```

</codetabs-item>

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

```php
$response = $client->getTask($response["task_id"]);

if ($response["status"] == "completed") {
  // success!
  echo $response["result"]["url"];
};
```

</codetabs-item>

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

```ruby
response = client.get_task(response["task_id"])

if response['status'] == 'completed'
  # success!
  puts(response['result']['url'])
```

</codetabs-item>

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

```java
var taskStatusResponse = TaskStatus.get(taskId).request();
// "completed".equals(taskStatusResponse.status);
```

</codetabs-item>

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

```csharp
// ITaskClient can provide the status of the export operation
var taskStatus = await taskClient.GetTaskStatusAsync(taskId);
if (taskStatus.Status == AsyncTaskStatus.Completed)
{
    // The export operation is completed
    // Result object contains the export file URL
    var exportedFileUrl = taskStatus.Result.Values.First().ToString();
}
```

</codetabs-item>

</codetabs>

<admonition type="info">

There is a limit on 10.000 messages being exported per user. Reach out to <https://getstream.io/contact/support/> for exporting users with >10,000 messages

</admonition>

## Exporting Users (sync)

<admonition type="warning">

NOTE: This endpoint is being deprecated in favor of the asynchronous endpoint documented above.

</admonition>

To export user data, Stream Chat exposes an `exportUser` method. This method can _only_ be called **server-side** due to security concerns, so please keep this in mind when attempting to make the call.

Below is an example of how to execute the call to export user data:

<codetabs>

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

```js
const data = await client.exportUser(userID);
```

</codetabs-item>

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

```python
response = client.export_user("user_id");
```

</codetabs-item>

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

```ruby
response = client.export_user('user_id')
```

</codetabs-item>

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

```php
$response = $client->exportUser($user["id"]);
```

</codetabs-item>

<codetabs-item value="go" label="Go">

```go
user, err := client.ExportUser(ctx, userID, nil)
```

</codetabs-item>

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

```csharp
await userClient.ExportAsync(user.Id);
```

</codetabs-item>

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

```java
User.export(userId).request();
```

</codetabs-item>

</codetabs>

The export will return all data about the user, including:

- User ID

- Messages

- Reactions

- Custom Data

<admonition type="warning">

Users with more than 10,000 messages will throw an error during the export process. Reach out to <https://getstream.io/contact/support/> for an export of a user with >10,000 messages

</admonition>

---

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

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