# Turkish Defense & Tech News Scraper (Savunma Sanayi) (`genkenobi/turkish-defense-news-scraper`) Actor

Scrapes Turkish defense-industry and national-technology news (savunma sanayi, milli teknoloji): full article text, article images, publish date, author and automatic tagging of defense companies and systems (ASELSAN, BAYKAR, TUSAS, ROKETSAN, KAAN, AKINCI, ATMACA and more).

- **URL**: https://apify.com/genkenobi/turkish-defense-news-scraper.md
- **Developed by:** [Burhan Hayber](https://apify.com/genkenobi) (community)
- **Categories:** News, Business, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 article scrapeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Turkish Defense & Tech News Scraper — Savunma Sanayi + Milli Teknoloji

Scrape Turkish **defense-industry** and **national-technology** news with the parts other news
scrapers leave out: **full article text**, **the article's own images**, publish date, author and
**automatic tagging of defense companies and weapon systems**.

Built for OSINT analysts, defense-industry market research, journalists, and AI agents that need
Turkish-language source material — not just headlines.

### What you get per article

| Field | Meaning |
|---|---|
| `title` | Headline (as published) |
| `url` | Publisher URL |
| `source` / `sourceKey` | Publisher name (e.g. `SavunmaSanayiST`) |
| `publishedAt` / `publishedRaw` | Publish date, ISO where available |
| `author` | Author or outlet account |
| `summary` | Lead / meta description |
| `text` | **Full article text** (Turkish) |
| `imageUrl` / `images[]` / `imageCount` | **Lead image plus all in-article images** |
| `companies` | Tagged companies/agencies: ASELSAN, BAYKAR, TUSAŞ, ROKETSAN, HAVELSAN, STM, OTOKAR, BMC, TÜBITAK SAGE, ASFAT, MKE, TEI, SSB, MSB, TOGG … |
| `systems` | Tagged systems/programmes: KAAN, AKINCI, BAYRAKTAR TB2/TB3, KIZILELMA, HÜRJET, HÜRKUŞ, GÖKBEY, ANKA, AKSUNGUR, MİLDEN, ALTAY, SİPER, HİSAR, GÖKDENİZ, ATMACA, ÇELİK KUBBE, İMECE … |
| `topics` | Theme tags: ihracat, seri-uretim, insansiz-hava, hava-savunma, uzay, test-basarisi, sozlesme, milli-teknoloji … |
| `language`, `wordCount`, `scrapedAt` | Basics for pipelines |

Tagging is language-aware (Turkish casing is handled: `İ`, `I`, `ı`, `Ş`, `Ğ` …), so `ASELSAN`
matches `ASELSAN`, `ASELSAN'ın` and `ASELSAN’a` alike.

### Sources

Verified with live HTTP checks — status, feed availability and image extraction:

| Key | Publisher | Type | Topic |
|---|---|---|---|
| `savunmasanayist` | SavunmaSanayiST | RSS | defense |
| `millisavunma` | Milli Savunma | RSS | defense |
| `aasavunma` | Anadolu Ajansı (Savunma) | RSS + URL filter | defense |
| `ssb` | Savunma Sanayii Başkanlığı (official) | HTML | defense |
| `kokpit` | Kokpit Aero | HTML | defense/aviation |
| `gdh` | GDH Digital | HTML | defense |
| `veryansin` | Veryansın TV | HTML | defense |
| `defenceturk` | DefenceTurk | HTML (proxy) | defense |
| `haberturk_tek` | Habertürk Teknoloji | HTML | milli teknoloji |
| `tubitak` | TÜBİTAK | HTML | milli teknoloji |
| `teknofest` | TEKNOFEST | HTML | milli teknoloji |

Some publishers block datacenter IPs (`DefenceTurk` answers `403` without a proxy). That is exactly
why this runs on Apify: switch on Apify Proxy and those sources work too. On overseas datacenters the
`ssb`, `tubitak` and `teknofest` sources may additionally be geo-restricted — use a Turkish proxy
group if a source returns nothing.

### Input example

```json
{
  "preset": "savunma",
  "keywords": ["KAAN", "İHA", "ihracat"],
  "maxItems": 50,
  "includeFullText": true,
  "includeImages": true,
  "dateFrom": "2026-09-01",
  "proxyConfiguration": { "useApifyProxy": true }
}
```

Leave `keywords` empty to get everything, or set `preset` to `teknoloji` for national technology,
or `alle` for both lanes.

### Output example

```json
{
  "title": "DELTAV Ramjet Motorlu Füze",
  "url": "https://www.millisavunma.com/deltav-ramjet-motorlu-fuze/",
  "source": "Milli Savunma",
  "publishedAt": "2026-06-10T22:50:17+00:00",
  "text": "Türkiye'nin savunma ve uzay teknolojileri alanındaki özel girişimlerinden biri olan DeltaV …",
  "imageUrl": "https://www.millisavunma.com/wp-content/uploads/2026/06/deltav_ramjet_01.jpg",
  "images": ["…/deltav_ramjet_01.jpg", "…/deltav_ramjet_03.jpg", "…/deltav_ramjet_05.jpg"],
  "imageCount": 5,
  "companies": ["ASELSAN"],
  "systems": ["ATMACA"],
  "topics": ["hava-savunma", "test-basarisi"],
  "wordCount": 668,
  "language": "tr"
}
```

### Use cases

- **OSINT & defense monitoring** — daily picture of the Turkish defense industry (procurement,
  exports, tests, programme milestones) with the source text for citations.
- **Market & supplier research** — who announces what, exports, capacity expansions, contracts.
- **AI agents & RAG** — Turkish-language corpus with images and entity tags, ready for embedding.
- **Media & content pipelines** — headline, lead photo and full text per story.

### Pricing

Pay per event: you are charged for each **article delivered** to the dataset. Nothing is charged for
articles that are filtered out (too short, keyword mismatch, duplicate).

### Notes & limits

- Text and images are extracted from the publishers' own public pages; copyright stays with the
  publisher. Check your own use case (quoting, monitoring, research) against their terms.
- Paywalled or login-only articles are not bypassed.
- The scraper is server-side (no browser): fast and cheap. Sources that need JavaScript or that
  hard-block datacenter IPs are best served with Apify Proxy enabled.
- New publishers get added; the source registry is data, not code, so extensions are cheap.

### Development

```bash
pip install -r requirements.txt
python3 -m src        # local run, input from storage/key_value_store/INPUT.json
apify run             # official local runner
apify push            # build & deploy to Apify
```

# Actor input Schema

## `preset` (type: `string`):

savunma = Verteidigungsindustrie (SavunmaSanayiST, Milli Savunma, SSB, Kokpit, GDH, Veryansin, DefenceTurk). tecnoloji = Milli Teknoloji (Habertürk Teknoloji, TÜBITAK, TEKNOFEST).

## `sources` (type: `array`):

Leer lassen = Preset nutzen. Werte: savunmasanayist, millisavunma, aasavunma, ssb, kokpit, gdh, veryansin, haberturk\_tek, tubitak, teknofest, defenceturk.

## `keywords` (type: `array`):

Nur Artikel ausliefern, die eines dieser Wörter enthalten (Titel, Zusammenfassung oder Text). Leer = alle. Beispiel: KAAN, İHA, ihracat.

## `maxItems` (type: `integer`):

Obergrenze fuer den gesamten Lauf (Abrechnung pro ausgeliefertem Artikel).

## `maxItemsPerSource` (type: `integer`):

Wie viele Kandidaten je Quelle von der Uebersichtsseite geladen werden, bevor gefiltert wird.

## `includeFullText` (type: `boolean`):

Volltext des Artikels in das Ergebnis schreiben (sonst nur Titel, Zusammenfassung, Bilder).

## `includeImages` (type: `boolean`):

og:image plus alle Artikelbilder im Inhalt.

## `minTextLength` (type: `integer`):

Kuerzere Artikel werden verworfen (verhindert Galerie-/Videoseiten im Datensatz).

## `dateFrom` (type: `string`):

ISO-Datum, z. B. 2026-09-01. Leer = kein Filter.

## `proxyConfiguration` (type: `object`):

Fuer Quellen, die ohne Proxy mit 403 antworten (z. B. DefenceTurk). Apify Proxy wird empfohlen.

## Actor input object example

```json
{
  "preset": "savunma",
  "maxItems": 40,
  "maxItemsPerSource": 8,
  "includeFullText": true,
  "includeImages": true,
  "minTextLength": 200
}
```

# Actor output Schema

## `articles` (type: `string`):

Array of scraped articles: title, url, source, publishedAt, summary, entities (companies/systems/topics), imageUrl.

## `runInfo` (type: `string`):

JSON object with run metadata: articles scraped, sources, duration, unique articles.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("genkenobi/turkish-defense-news-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("genkenobi/turkish-defense-news-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call genkenobi/turkish-defense-news-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,genkenobi/turkish-defense-news-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/q005K9RtJWatU1ItB/builds/ffGx0IuSlzOyi6UNC/openapi.json
