[cdpfleet](https://cdpfleet.com/) / [Browsers](https://cdpfleet.com/browsers) / Naver Whale

Chromium family · Naver's Chromium browser

# Naver Whale, *one socket* away.

Naver Whale, the browser that ships with Naver services in Korea. Stable channel.

[Open in the code builder](https://cdpfleet.com/docs/builder?browser=whale)[Reference](https://cdpfleet.com/docs/browsers/whale)

-   **/whale/session**launch endpoint
-   **1.60**Playwright client
-   **1**thread headless

## Why Naver Whale

-   **Naver Whale**: `Whale/…` in the user agent and `Whale` in the client hints — what Korean sites see from Naver's own browser.
-   Testing pages for Korean audiences.
-   Headful for sites that read the user agent closely: headless says `HeadlessChrome`.

## Versions on the fleet now

**stable**5.41.429.5

Choose a build with `channel`; without one you get stable.

New majors are announced on [/docs/updates](https://cdpfleet.com/docs/updates).

## Launch it

One HTTPS call to `POST /whale/session` returns a WebSocket URL; connect to it with Playwright's `chromium.connect()` (client 1.60). A headless session takes 1 thread, a headful one 2.

Naver Whale: launch, open a page, print its title

 

```node
// npm install playwright@1.60.0
// Browsers run on cdpfleet, so no `npx playwright install` is needed.
import { chromium } from 'playwright';

const KEY = process.env.CDPFLEET_API_KEY;

// 1. Launch the browser
const res = await fetch('https://starter.cdpfleet.com/whale/session', {
  method: 'POST',
  headers: { 'x-api-key': KEY, 'content-type': 'application/json' },
  body: JSON.stringify({
    proxy: 'http://user:pass@proxy.example.com:8080',
    headless: 'new',
  }),
});
if (!res.ok) throw new Error(`launch failed: ${res.status} ${await res.text()}`);
const { wsUrl } = await res.json();

// 2. Connect and drive it
const browser = await chromium.connect(wsUrl, { headers: { 'x-api-key': KEY } });
const page = await browser.newPage();
await page.goto('https://example.com');
console.log(await page.title());
await browser.close(); // ends the session and stops billing
```

```python
# pip install playwright==1.60.0 requests
# Browsers run on cdpfleet, so no `playwright install` is needed.
import os
import requests
from playwright.sync_api import sync_playwright

KEY = os.environ["CDPFLEET_API_KEY"]

# 1. Launch the browser
res = requests.post(
    "https://starter.cdpfleet.com/whale/session",
    headers={"x-api-key": KEY},
    json={
        "proxy": "http://user:pass@proxy.example.com:8080",
        "headless": "new",
    },
    timeout=60,
)
res.raise_for_status()
ws_url = res.json()["wsUrl"]

# 2. Connect and drive it
with sync_playwright() as p:
    browser = p.chromium.connect(ws_url, headers={"x-api-key": KEY})
    page = browser.new_page()
    page.goto("https://example.com")
    print(page.title())
    browser.close()  # ends the session and stops billing
```

```java
// Maven: com.microsoft.playwright:playwright:1.60.0  and  com.google.code.gson:gson:2.11.0
// Run with PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1: browsers run on cdpfleet.
import com.google.gson.JsonParser;
import com.microsoft.playwright.*;
import java.net.URI;
import java.net.http.*;
import java.util.Map;

public class Example {
  public static void main(String[] args) throws Exception {
    String key = System.getenv("CDPFLEET_API_KEY");

    // 1. Launch the browser
    String body = """
        {
          "proxy": "http://user:pass@proxy.example.com:8080",
          "headless": "new"
        }
        """;
    HttpResponse<String> res = HttpClient.newHttpClient().send(
        HttpRequest.newBuilder(URI.create("https://starter.cdpfleet.com/whale/session"))
            .header("x-api-key", key)
            .header("content-type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(body))
            .build(),
        HttpResponse.BodyHandlers.ofString());
    if (res.statusCode() != 200) {
      throw new RuntimeException("launch failed: " + res.statusCode() + " " + res.body());
    }
    String wsUrl = JsonParser.parseString(res.body()).getAsJsonObject().get("wsUrl").getAsString();

    // 2. Connect and drive it
    try (Playwright playwright = Playwright.create()) {
      Browser browser = playwright.chromium().connect(wsUrl,
          new BrowserType.ConnectOptions().setHeaders(Map.of("x-api-key", key)));
      Page page = browser.newPage();
      page.navigate("https://example.com");
      System.out.println(page.title());
      browser.close(); // ends the session and stops billing
    }
  }
}
```

```csharp
// dotnet add package Microsoft.Playwright --version 1.60.0
// Browsers run on cdpfleet, so no `playwright install` is needed.
using System.Net.Http.Json;
using System.Text;
using System.Text.Json;
using Microsoft.Playwright;

var key = Environment.GetEnvironmentVariable("CDPFLEET_API_KEY")!;

// 1. Launch the browser
using var http = new HttpClient();
http.DefaultRequestHeaders.Add("x-api-key", key);
var body = """
    {
      "proxy": "http://user:pass@proxy.example.com:8080",
      "headless": "new"
    }
    """;
var res = await http.PostAsync("https://starter.cdpfleet.com/whale/session",
    new StringContent(body, Encoding.UTF8, "application/json"));
if (!res.IsSuccessStatusCode)
    throw new Exception($"launch failed: {(int)res.StatusCode} {await res.Content.ReadAsStringAsync()}");
var wsUrl = (await res.Content.ReadFromJsonAsync<JsonElement>()).GetProperty("wsUrl").GetString()!;

// 2. Connect and drive it
using var playwright = await Playwright.CreateAsync();
var browser = await playwright.Chromium.ConnectAsync(wsUrl, new BrowserTypeConnectOptions
{
    Headers = new Dictionary<string, string> { ["x-api-key"] = key },
});
var page = await browser.NewPageAsync();
await page.GotoAsync("https://example.com");
Console.WriteLine(await page.TitleAsync());
await browser.CloseAsync(); // ends the session and stops billing
```

```go
// go get github.com/playwright-community/playwright-go@v0.6000.0
//
// One-time driver setup (needs Node.js 18+): playwright-go can no longer download the
// 1.60.0 driver itself, so build it from npm and point PLAYWRIGHT_DRIVER_PATH at it:
//   mkdir -p ~/.cache/pw-driver-1.60.0 && cd ~/.cache/pw-driver-1.60.0 &&
//     curl -sL https://registry.npmjs.org/playwright-core/-/playwright-core-1.60.0.tgz | tar xz &&
//     ln -sf "$(command -v node)" node
//   export PLAYWRIGHT_DRIVER_PATH=~/.cache/pw-driver-1.60.0
// Browsers run on cdpfleet, so no browsers are downloaded (SkipInstallBrowsers).
package main

import (
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"strings"

	"github.com/playwright-community/playwright-go"
)

func main() {
	key := os.Getenv("CDPFLEET_API_KEY")

	// 1. Launch the browser
	body := `{
	  "proxy": "http://user:pass@proxy.example.com:8080",
	  "headless": "new"
	}`
	req, _ := http.NewRequest("POST", "https://starter.cdpfleet.com/whale/session", strings.NewReader(body))
	req.Header.Set("x-api-key", key)
	req.Header.Set("content-type", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer res.Body.Close()
	if res.StatusCode != http.StatusOK {
		msg, _ := io.ReadAll(res.Body)
		log.Fatalf("launch failed: %s %s", res.Status, msg)
	}
	var session struct {
		WsURL string `json:"wsUrl"`
	}
	if err := json.NewDecoder(res.Body).Decode(&session); err != nil {
		log.Fatal(err)
	}

	// 2. Connect and drive it (Install fetches only the Playwright driver, once)
	opts := &playwright.RunOptions{SkipInstallBrowsers: true}
	if err := playwright.Install(opts); err != nil {
		log.Fatal(err)
	}
	pw, err := playwright.Run(opts)
	if err != nil {
		log.Fatal(err)
	}
	defer pw.Stop()
	browser, err := pw.Chromium.Connect(session.WsURL, playwright.BrowserTypeConnectOptions{
		Headers: map[string]string{"x-api-key": key},
	})
	if err != nil {
		log.Fatal(err)
	}
	page, err := browser.NewPage()
	if err != nil {
		log.Fatal(err)
	}
	if _, err := page.Goto("https://example.com"); err != nil {
		log.Fatal(err)
	}
	title, _ := page.Title()
	fmt.Println(title)
	browser.Close() // ends the session and stops billing
}
```

[This program on GitHub →](https://github.com/cdpfleet/cdpfleet/tree/main/examples/browsers/whale)

## Launch options

| Option | What it does |
| --- | --- |
| [`proxy_rules`](https://cdpfleet.com/docs/browsers/whale#opt-proxy_rules) | Send specific destination hosts through specific proxies. |
| [`inactivity_timeout`](https://cdpfleet.com/docs/browsers/whale#opt-inactivity_timeout) | End the session after this long with no traffic on its WebSocket. |
| [`overall_timeout`](https://cdpfleet.com/docs/browsers/whale#opt-overall_timeout) | Hard cap on the session's total lifetime, regardless of activity. |
| [`memory`](https://cdpfleet.com/docs/browsers/whale#opt-memory) | Give the session 2, 3 or 4 times your plan's memory; it counts as that many times the threads. |
| [`downloads`](https://cdpfleet.com/docs/browsers/whale#opt-downloads) | Keep every file the browser downloads, to fetch after the session. |
| [`vpn_tunnel`](https://cdpfleet.com/docs/browsers/whale#opt-vpn_tunnel) | VPN Tunnel: UDP/WebRTC full support — all of the browser's traffic, UDP included, goes through the residential exit. |
| [`vpn`](https://cdpfleet.com/docs/browsers/whale#opt-vpn) | Own network (dedicated plans): send all of the browser's traffic through your own VPN instead of a proxy. |
| [`headless`](https://cdpfleet.com/docs/browsers/whale#opt-headless) | Run without a display. |
| [`channel`](https://cdpfleet.com/docs/browsers/whale#opt-channel) | Release channel of the browser build. |
| [`screencast`](https://cdpfleet.com/docs/browsers/whale#opt-screencast) | Stream the page to your code (Playwright page.screencast). |
| [`live_view`](https://cdpfleet.com/docs/browsers/whale#opt-live_view) | Make a headless session watchable and controllable from outside. |
| [`screen_size`](https://cdpfleet.com/docs/browsers/whale#opt-screen_size) | Resolution of the session's own display (headful only). |
| [`keep_alive`](https://cdpfleet.com/docs/browsers/whale#opt-keep_alive) | Keep the session when your client disconnects (dedicated threads only). |
| [`start_url`](https://cdpfleet.com/docs/browsers/whale#opt-start_url) | Open this page at launch so the session can be driven in live view with no client connected. |
| [`record`](https://cdpfleet.com/docs/browsers/whale#opt-record) | Opt this session out of recording with false. |

Every session also needs a `proxy` — yours, or the [residential proxy](https://cdpfleet.com/residential-proxy).

## Related

Cases, recipes, posts and comparisons about this — updated as new ones are published.

### Reference docs

The details, options and errors.

-   [Naver Whale reference](https://cdpfleet.com/docs/browsers/whale)Versions and every launch option.
-   [Quickstart](https://cdpfleet.com/docs/quickstart)Your first session in five minutes.

### Cases 6

Real problems solved end to end, run on production in five languages.

-   [Case 84: Does the TLS fingerprint (JA4) explain which browsers got in? Twelve browsers against six vendors](https://cdpfleet.com/docs/cases/ja4-vs-vendor-verdicts)Each of the twelve browsers from the real-site lab week loads a TLS echo page once, so we know the JA4, peetprint and HTTP/2 fingerprint it sends. Grouped by…[Code on GitHub](https://github.com/cdpfleet/cdpfleet/tree/main/cases/84-ja4-vs-vendor-verdicts)
-   [Case 77: Kasada and AWS WAF on real sites: twelve browsers, four sites, one exit each](https://cdpfleet.com/docs/cases/kasada-and-aws-waf-by-browser)Two real sites behind Kasada and two behind AWS WAF, loaded once by each of twelve browsers and by a returning Camoufox profile, through one sticky residential exit…[Code on GitHub](https://github.com/cdpfleet/cdpfleet/tree/main/cases/77-kasada-and-aws-waf-by-browser)
-   [Case 75: HUMAN on real sites: twelve browsers, three sites, one exit each](https://cdpfleet.com/docs/cases/human-real-sites-by-browser)Three real sites behind HUMAN (formerly PerimeterX), chosen from our sweep as easy, medium and hard, loaded once by each of twelve browsers and by a returning…[Code on GitHub](https://github.com/cdpfleet/cdpfleet/tree/main/cases/75-human-real-sites-by-browser)
-   [Case 73: Akamai on real sites: twelve browsers, three sites, one exit each](https://cdpfleet.com/docs/cases/akamai-real-sites-by-browser)Three real sites behind Akamai Bot Manager, chosen from our sweep as easy, medium and hard, loaded once by each of twelve browsers and by a returning Camoufox…[Code on GitHub](https://github.com/cdpfleet/cdpfleet/tree/main/cases/73-akamai-real-sites-by-browser)
-   [Case 71: DataDome on real sites: twelve browsers, three sites, one exit each](https://cdpfleet.com/docs/cases/datadome-real-sites-by-browser)Three real sites behind DataDome, chosen from our sweep as easy, medium and hard, loaded once by each of twelve browsers and by a returning Camoufox profile, all…[Code on GitHub](https://github.com/cdpfleet/cdpfleet/tree/main/cases/71-datadome-real-sites-by-browser)
-   [Case 70: Cloudflare on real sites: twelve browsers, three sites, one exit each](https://cdpfleet.com/docs/cases/cloudflare-real-sites-by-browser)Three real sites behind Cloudflare, chosen from our sweep as easy, medium and hard, loaded once by each of twelve browsers and by a returning Camoufox profile, all…[Code on GitHub](https://github.com/cdpfleet/cdpfleet/tree/main/cases/70-cloudflare-real-sites-by-browser)

### Recipes 1

Complete programs for one setup each.

-   [Naver Whale](https://cdpfleet.com/docs/examples#whale)Naver's browser (Whale 5.39 on Chromium 150): `Whale/…` in the user agent and `Whale` in the client hints — what Korean sites see from Naver's own browser. Headless…[Code on GitHub](https://github.com/cdpfleet/cdpfleet/tree/main/examples/recipes/whale)

### Updates 1

Product news and browser releases.

-   [Whale 5.41: Chromium 150 to 156 in one step, and now Chrome's TLS fingerprint](https://cdpfleet.com/docs/updates/whale-5-41)Stable Whale on the fleet is now 5.41.429.3, on Chromium 156: six Chromium majors at once, Chrome's JA4, plain HTTP still loads, Shared Storage gone.

### Browser comparisons 1

Measured side by side on the fleet.

-   [Naver Whale vs Chrome](https://cdpfleet.com/docs/compare/whale-vs-chrome)Whale 5.41 runs on Chromium 156, one major behind Chrome 157, names itself in the user agent and client hints, and now sends the same TLS hello as Chrome. What that…

## Read next

[Browsers →](https://cdpfleet.com/browsers)[Google Chrome →](https://cdpfleet.com/browsers/chrome)[Microsoft Edge →](https://cdpfleet.com/browsers/edge)[Brave →](https://cdpfleet.com/browsers/brave)

---
Source: https://cdpfleet.com/browsers/whale · Markdown: https://cdpfleet.com/browsers/whale.md · All docs for AI tools: https://cdpfleet.com/llms.txt
