Verwenden Sie die Microsoft Web IQ SDKs für Python und TypeScript

Offizielle SDKs für die Microsoft Web IQ API, verfügbar in Python und TypeScript. Diese SDKs bieten Ihren Anwendungen Echtzeitzugriff auf die Websuche, die Videosuche, das Browsen, die Nachrichtensuche und die Bildersuche — konzipiert, um LLM-Antworten mit genauen, aktuellen Informationen zu fundieren.

Python TypeScript
Pakete pip install webiq npm install @microsoft/webiq
Laufzeit Python 3.11+ Node.js 22+
Lizenz MIT MIT

Installation

Python

pip install webiq

TypeScript

npm install @microsoft/webiq

Quickstart

Python Leitfaden

import os
from webiq import WebIQClient
from webiq.types import BrowseContentFormat, ContentFormat

with WebIQClient(api_key=os.environ["WEBIQ_API_KEY"]) as client:
    # Web search
    web = client.web.search(
        "Python programming",
        max_results=5,
        content_format=ContentFormat.passage,
    )
    for r in web.webResults or []:
        print(r.title, r.url)

    # Videos search
    videos = client.videos.search("machine learning tutorial", max_results=5)
    for v in videos.videoResults or []:
        print(v.title, v.length)

    # Browse a URL
    page = client.browse.fetch("https://www.microsoft.com", content_format=BrowseContentFormat.markdown)
    print(page.content)

    # News search
    news = client.news.search("technology", max_results=5)
    for item in news.newsResults or []:
        print(item.title, "-", item.source)

    # Image search
    images = client.images.search("golden gate bridge", max_results=5)
    for img in images.imageResults or []:
        print(img.title, img.url)

TypeScript-Leitfaden

import { WebIQClient, BrowseContentFormat, ContentFormat } from '@microsoft/webiq';

async function main() {
  const client = new WebIQClient({ apiKey: process.env.WEBIQ_API_KEY });

  // Web search
  const web = await client.web.search('TypeScript programming', {
    maxResults: 5,
    contentFormat: ContentFormat.PASSAGE,
  });
  for (const r of web.webResults ?? []) console.log(r.title, r.url);

  // Videos search
  const videos = await client.videos.search('machine learning tutorial');
  for (const v of videos.videoResults ?? []) console.log(v.title, v.length);

  // Browse a URL
  const page = await client.browse.fetch('https://www.microsoft.com', {
    contentFormat: BrowseContentFormat.MARKDOWN,
  });
  console.log(page.content);

  // News search
  const news = await client.news.search('technology', { maxResults: 5 });
  for (const item of news.newsResults ?? []) console.log(item.title, '-', item.source);

  // Image search
  const images = await client.images.search('golden gate bridge', { maxResults: 5 });
  for (const img of images.imageResults ?? []) console.log(img.title, img.url);

  await client.close();
}

main().catch(console.error);

Authentication

API-Schlüssel

# Python
import os
from webiq import WebIQClient

client = WebIQClient(api_key=os.environ["WEBIQ_API_KEY"])
// TypeScript
import { WebIQClient } from '@microsoft/webiq';

const client = new WebIQClient({ apiKey: process.env.WEBIQ_API_KEY });

Microsoft Entra ID

Übergeben Sie eine beliebige Azure Identity TokenCredential.

# Python — uses `azure-identity`
from azure.identity import DefaultAzureCredential
from webiq import WebIQClient

client = WebIQClient(credential=DefaultAzureCredential())
// TypeScript — uses `@azure/identity`
import { DefaultAzureCredential } from '@azure/identity';
import { WebIQClient } from '@microsoft/webiq';

const client = new WebIQClient({
  credential: new DefaultAzureCredential(),
});

SDK-Ressourcen und -Methoden

Der Client macht fünf Ressourcennamespaces verfügbar: web, videos, browse, news und images.

client.web.search() — Durchsuchen Sie das Web, und rufen Sie Seiteninhalte zur Fundierung ab.

response = client.web.search(
    query="search terms",          # Required, 1–1000 chars
    max_results=10,                # 1–50 (default 10)
    language="en",                 # ISO 639-1 code
    region="US",                   # Country/region code
    location="lat:40.7;long:-74.0",  # Optional
    content_format=ContentFormat.passage,   # passage (default) | text | html | markdown (full-page content)
    max_length=3000,               # Max content chars (default 3000)
)
# response.webResults → list of { title, url, content, lastUpdatedAt, crawledAt, language, isAdult }

client.videos.search() – Suchen Sie relevante Videoinhalte mit optionaler Wiedergabelistenunterstützung.

response = client.videos.search(
    query="search terms",          # Required, 1–1000 chars
    max_results=30,                # 1–30 (default 30)
    language="en",
    region="US",
    enable_playlist=True,          # Include playlist results
    freshness="month",             # week | month | year
)
# response.videoResults → list of { title, url, description, length, viewCount, moments[], thumbnailUrl, ... }
# response.playlists   → list of { title, videos[] }

Durchsuchen

client.browse.fetch() — Inhalte aus einer beliebigen URL extrahieren. Unterstützt Live-Crawling und JavaScript-Rendering.

response = client.browse.fetch(
    url="https://www.microsoft.com",   # Required
    max_length=10000,                  # Max content chars, 1–500000
    live_crawl="fallback",             # "none" (cached only, default) | "fallback" (crawl if not cached) | "force" (always crawl, bypass cache)
    include_web_links=True,            # Include outbound hyperlinks
    include_image_links=True,          # Include image URLs
    render_dynamic_pages=False,        # JS rendering (requires live_crawl="fallback")
    content_format=BrowseContentFormat.markdown,   # text | html | markdown
)
# response → { url, title, content, isAdult, lastUpdatedAt, crawledAt, retryAfter, traceId }

client.news.search() – Holen Sie sich die neuesten Nachrichtenartikel mit den Passagen, die für die Abfrage am relevantesten sind.

response = client.news.search(
    query="search terms",          # Required, 1–1000 chars
    max_results=10,                # 1–20 (default 10)
    language="en",
    region="US",
    location="lat:40.7;long:-74.0",  # Optional
    content_format=ContentFormat.passage,
    max_length=3000,
)
# response.newsResults → list of { title, url, content, source, lastUpdatedAt, thumbnail, isAdult }

client.images.search() — Bilder mit Filterung nach Seitenverhältnis, Größe und sicherer Suche suchen.

from webiq.types import ImageAspectRatio, ImageSize, SafeSearch

response = client.images.search(
    query="search terms",          # Required, 1–1000 chars
    max_results=30,                # 1–30 (default 30)
    language="en",
    region="US",
    aspect_ratio=ImageAspectRatio.wide,   # square | wide | tall
    image_size=ImageSize.large,           # small | medium | large | extraLarge
    safe_search=SafeSearch.strict,        # off | strict
    watermark_free=True,
)
# response.imageResults → list of { title, url, hostPageUrl, caption, width, height, thumbnailUrl, ... }

Note

TypeScript-Methoden verwenden dieselben Parameter in camelCase (z. B. maxResults, contentFormat, liveCrawl, aspectRatio). Informationen zur Aufrufkonvention finden Sie oben im TypeScript-Schnellstart.


Asynchroner Support

Python Support

import asyncio
from webiq import WebIQAsyncClient

async def main():
    async with WebIQAsyncClient(api_key="your-api-key") as client:
        web, news = await asyncio.gather(
            client.web.search("async Python"),
            client.news.search("programming"),
        )
        for r in web.webResults or []:
            print(r.title)

asyncio.run(main())

TypeScript-Unterstützung

TypeScript ist nativ asynchron. Verwenden Sie Promise.all für Parallelität:

const [web, news, videos] = await Promise.all([
  client.web.search('TypeScript'),
  client.news.search('programming'),
  client.videos.search('tutorial'),
]);

Configuration

Timeout und Wiederholen

Der Client akzeptiert timeout und retry als Optionen auf oberster Ebene. Bei jedem Aufruf timeout jeder Ressourcenmethode wird der Standardwert auf Clientebene außer Kraft gesetzt. Das SDK versucht 408, 502, 500, 503, 504 automatisch erneut mit exponentiellem Backoff und Jitter; wenn der Antworttext ein retryAfter-Feld (z. B. "30s") enthält, wartet das SDK auf diesen Hinweis anstelle der Backoff-Verzögerung. 429 und 430 werden niemals automatisch wiederholt – sie werden sofort als RateLimitError angezeigt, damit Ihre Anwendung eine eigene Back-off-Richtlinie anwenden kann. Clientseitige Timeouts werden ebenfalls nicht erneut versucht (sie lösen APIConnectionError aus).

# Python
from webiq import WebIQClient, RetryPolicy

client = WebIQClient(
    api_key="your-api-key",
    timeout=10.0,                  # seconds (default: 10.0)
    retry=RetryPolicy(
        max_retries=2,             # defaults shown
        base_delay_s=0.25,
        max_delay_s=4.0,
    ),
)

# Per-call override
response = client.web.search("query", language="de", region="DE", timeout=30.0)
// TypeScript
import { WebIQClient, RetryPolicy } from '@microsoft/webiq';

const client = new WebIQClient({
  apiKey: 'your-api-key',
  timeout: 10000, // milliseconds (default: 10000)
  retry: new RetryPolicy({
    maxRetries: 2, // defaults shown
    baseDelaySeconds: 0.25,
    maxDelaySeconds: 4.0,
  }),
});

Angepasster HTTP-Client (Proxy, TLS, ...)

Für erweiterte HTTP-Einstellungen – Proxy, benutzerdefiniertes TLS, Verbindungspooling usw. Das SDK schließt keine aufrufereigenen Clients.

# Python — pass a pre-configured `httpx.Client` via `http_client`
import httpx
from webiq import WebIQClient, WebIQAsyncClient

# sync
http_client = httpx.Client(
  base_url="https://api.microsoft.ai/v3",
  proxy="http://proxy:8080",
)
client = WebIQClient(api_key="your-api-key", http_client=http_client)

# async
http_client = httpx.AsyncClient(
  base_url="https://api.microsoft.ai/v3",
  proxy="http://proxy:8080",
)
client = WebIQAsyncClient(api_key="your-api-key", http_client=http_client)
// TypeScript — pass a custom `fetchFn` that wraps the global `fetch`
import { ProxyAgent } from 'undici';
import { WebIQClient } from '@microsoft/webiq';

const proxyAgent = new ProxyAgent('http://my-proxy:8080');

const client = new WebIQClient({
  apiKey: 'your-api-key',
  // Spread `init` so headers, body, and the SDK's internal `AbortSignal` are preserved.
  fetchFn: (url, init) => fetch(url, { ...init, dispatcher: proxyAgent }),
});

Stornierung (TypeScript)

Jede TypeScript-Ressourcenmethode akzeptiert eine AbortSignal Via options.signal. Wenn das Signal abbricht, wird die In-Flight-Anforderung abgebrochen, die Wiederholungsversuche beendet, und reason des Signals wird unverändert erneut geworfen (ohne APIConnectionError-Wrapper).

// Apply a wall-clock budget that includes retries (the `timeout` option is per attempt only)
const result = await client.web.search('latest news', {
  signal: AbortSignal.timeout(5_000),
});

// Combine signals (e.g. an inbound request signal plus a wall-clock cap)
const result2 = await client.web.search('latest news', {
  signal: AbortSignal.any([req.signal, AbortSignal.timeout(5_000)]),
});

Telemetrie-Hook

Überwachen Sie jede Anfrage/Antwort auf Protokollierung, Metriken oder Debugging.

# Python
from webiq import WebIQClient, TelemetryEvent

def on_request(event: TelemetryEvent):
    print(f"{event.method} {event.path} → {event.status_code} ({event.elapsed_ms}ms)")

client = WebIQClient(api_key="your-api-key", telemetry_hook=on_request)
// TypeScript
import { WebIQClient, TelemetryEvent } from '@microsoft/webiq';

const client = new WebIQClient({
  apiKey: 'your-api-key',
  telemetryHook: (event: TelemetryEvent) => {
    console.log(`${event.method} ${event.path} → ${event.statusCode} (${event.elapsedMs}ms)`);
  },
});

Die TelemetryEvent Felder sind:

  • Python (snake_case): method, path, transport, attempt, request_id, status_code, trace_id, retry_after, elapsed_ms, error, error_body
  • TypeScript (camelCase): method, path, transport, attempt, statusCode, requestId, retryAfter, traceId, elapsedMs, error, errorBody

Fehlerbehandlung

Beide SDKs bieten typierte Ausnahmen für die strukturierte Fehlerbehandlung. Alle Fehler erben von WebIQError.

Exception HTTP-Status Trigger
AuthenticationError 401 Ungültiger oder fehlender API-Schlüssel
PermissionDeniedError 403 Authentifiziert, aber nicht für die Ressource autorisiert
RateLimitError 429, 430 Ratenlimit / Grenze für gleichzeitige Anfragen überschritten
APIStatusError 400, 404, 500, 503, 504, ... Alle anderen HTTP-Fehler
APIConnectionError — Netzwerkprobleme, DNS-Fehler, Timeouts
WebIQError — Basisklasse für alle SDK-Fehler

PermissionDeniedError und RateLimitError sind beide Unterklassen von APIStatusError, sodass ein breiterer Handler für APIStatusError sie weiterhin erfasst. Das SDK führt keine429 / 430-Antworten automatisch erneut aus – der Back-off-Hinweis des Servers ist über error.retry_after (Python) / error.retryAfter (TypeScript) für Ihre Anwendung verfügbar.

# Python
from webiq import (
    WebIQError,
    APIConnectionError,
    APIStatusError,
    AuthenticationError,
    PermissionDeniedError,
    RateLimitError,
)

try:
    response = client.web.search("test")
except PermissionDeniedError as e:
    # 403 — authenticated, but not allowed to call this resource
    print(f"Forbidden (HTTP {e.status_code}): {e}")
except AuthenticationError as e:
    # 401 — invalid or missing API key
    print(f"Auth failed (HTTP {e.status_code}): {e}")
except RateLimitError as e:
    # 429 or 430 — rate limit / concurrent-request limit (never auto-retried)
    print(f"Rate limited. Retry after: {e.retry_after}")
except APIStatusError as e:
    print(f"API error (HTTP {e.status_code}): {e}")
except APIConnectionError as e:
    print(f"Connection failed: {e}")
except WebIQError as e:
    print(f"SDK error: {e}")
// TypeScript
import {
  WebIQError,
  APIConnectionError,
  APIStatusError,
  AuthenticationError,
  PermissionDeniedError,
  RateLimitError,
} from '@microsoft/webiq';

try {
  const results = await client.web.search('test');
} catch (error) {
  if (error instanceof PermissionDeniedError) {
    // 403 — authenticated, but not allowed to call this resource
    console.error(`Forbidden (HTTP ${error.statusCode}):`, error.message);
  } else if (error instanceof AuthenticationError) {
    // 401 — invalid or missing API key
    console.error(`Auth failed (HTTP ${error.statusCode}):`, error.message);
  } else if (error instanceof RateLimitError) {
    // 429 or 430 — rate limit / concurrent-request limit (never auto-retried)
    console.error(`Rate limited. Retry after: ${error.retryAfter}`);
  } else if (error instanceof APIStatusError) {
    console.error(`API error (HTTP ${error.statusCode}):`, error.message);
  } else if (error instanceof APIConnectionError) {
    console.error('Connection failed:', error.message);
  }
}

Fehlerdetails überprüfen

Alle APIStatusError Instanzen (einschließlich PermissionDeniedError und RateLimitError) machen den vollständigen Fehlerantworttext verfügbar. Die meisten Eingabevalidierungsprobleme im Python SDK (z. B. max_results außerhalb des Bereichs, leer query) werden clientseitig von Pydantic abgefangen und lösen pydantic.ValidationError aus, bevor eine Anforderung gesendet wird; das folgende Muster gilt, wenn der Server eine Anforderung ablehnt. browse.fetch ist eine bequeme Möglichkeit, eins auszulösen – eine fehlende oder gefilterte URL wird als strukturierter Fehler angezeigt:

# Python
from webiq import WebIQClient
from webiq.errors import APIStatusError

client = WebIQClient(api_key="your-api-key")

try:
    response = client.browse.fetch("https://www.not-microsoft.com")
except APIStatusError as e:
    print(f"Status: {e.status_code}")                          # e.g. 404
    print(f"Message: {e}")                                      # e.g. "No result is found"
    if isinstance(e.body, dict):
        print(f"Error code: {e.body.get('errorCode')}")        # e.g. "BrowseApiDocNotFound"
        print(f"Category: {e.body.get('errorCategory')}")      # e.g. "UserError"
        print(f"Details: {e.body.get('technicalDetails')}")    # e.g. "NotFound"
        print(f"Trace ID: {e.body.get('traceId')}")
        print(f"Retry after: {e.body.get('retryAfter')}")
// TypeScript
import { WebIQClient, APIStatusError } from '@microsoft/webiq';

async function main() {
  const client = new WebIQClient({ apiKey: 'your-api-key' });

  try {
    await client.browse.fetch('https://www.not-microsoft.com');
  } catch (error) {
    if (error instanceof APIStatusError) {
      console.error(`Status: ${error.statusCode}`); // e.g. 404
      console.error(`Message: ${error.message}`); // e.g. "No result is found"

      // Full error body from the API response
      if (error.body && typeof error.body === 'object') {
        const body = error.body as Record<string, unknown>;
        console.error(`Error code: ${body.errorCode}`); // e.g. "BrowseApiDocNotFound"
        console.error(`Category: ${body.errorCategory}`); // e.g. "UserError"
        console.error(`Details: ${body.technicalDetails}`); // e.g. "NotFound"
        console.error(`Trace ID: ${body.traceId}`); // for debugging with support
        console.error(`Retry after: ${body.retryAfter}`); // for retryable errors
      }
    }
  }
}

main().catch(console.error);

Tipps zum Debuggen

  • traceId — Jede Antwort enthält ein traceId Feld für das End-to-End-Debugging. Schließen Sie sie ein, wenn Sie sich an den Support wenden.
  • Telemetrie-Hook – Fügen Sie einen Rückruf an, um jeden Anforderungsversuch, Statuscode und Zeitangaben zu protokollieren.
  • Fehlertext - APIStatusError.body enthält die vollständige Serverantwort, einschließlich errorCode, errorCategory, technicalDetails und traceId.