diff --git a/assets/css/custom.css b/assets/css/custom.css
index 9b7cf50a1356d41530baa447984f2fb2abfd873a..5cba8ecf80180ee7ea93f79b3754f18e9afd0141 100755
--- a/assets/css/custom.css
+++ b/assets/css/custom.css
@@ -289,4 +289,27 @@ card .formRegis{
 
 .ui.segment.kop {
   line-height: 5px;
+}
+
+.search-container {
+  width: fit-content;
+  margin: auto;
+}
+
+.search-form {
+  border: none;
+  border-bottom: solid #0d5aa7 2px;
+  text-decoration: none;
+  outline: none;
+  font-size: 14pt;
+}
+
+.search-button {
+  background-color: #0d5aa7;
+  color: white;
+  border: none;
+  padding: 10px;
+  font-size: 14pt;
+  border-radius: 5px;
+  margin-left: 10px;
 }
\ No newline at end of file
diff --git a/assets/js/components/Pagination.jsx b/assets/js/components/Pagination.jsx
index d2a50ae2229e941d73ec3c5eda0a4c534f620ded..d278cb504272e2aaa86c59b7f2c7dec67d3a2de0 100644
--- a/assets/js/components/Pagination.jsx
+++ b/assets/js/components/Pagination.jsx
@@ -2,6 +2,7 @@ import React from 'react';
 import { Menu, Container, Icon, Loader } from 'semantic-ui-react';
 import Server from '../lib/Server';
 import ModalAlert from '../components/ModalAlert';
+import Pane from "./Pane";
 
 
 export default class Pagination extends React.Component {
@@ -29,38 +30,85 @@ export default class Pagination extends React.Component {
       dir: 0,
       start: true,
       finish: false,
+      search: '',
     };
     this.handleNext = this.handleNext.bind(this);
     this.handlePrev = this.handlePrev.bind(this);
     this.getItemsData = this.getItemsData.bind(this);
     this.handleMovement = this.handleMovement.bind(this);
+    this.handleSearchChange = this.handleSearchChange.bind(this);
+    this.handleSearchSubmit = this.handleSearchSubmit.bind(this);
     this.refresh = this.refresh.bind(this);
     this.content = this.content.bind(this);
     this.pageMenu = this.pageMenu.bind(this);
     this.getItemsData();
   }
 
-  getItemsData = () => Server.get(this.state.url, false).then((data) => {
-    this.setState({ current: this.state.current + this.state.dir });
-    this.setState(
-      { items: data.results,
-        next: `${this.props.url}?page=${this.state.current + 1}`,
-        prev: `${this.props.url}?page=${this.state.current - 1}`,
-        loading: false,
+  getItemsData = () => {
+    const prefix = this.state.dir === 0 ? '?' : '&';
+    const searchPrefix = this.state.search !== '' ? prefix : '';
+    const searchValue = this.state.search !== '' ? `search=${this.state.search}` : '';
+    return Server.get(`${this.state.url}${searchPrefix}${searchValue}`, false).then((data) => {
+      console.log('GET ITEM DATA');
+      this.setState({
+        current: this.state.current + this.state.dir,
+      });
+      this.setState(
+        {
+          items: data.results,
+          next: `${this.props.url}?page=${this.state.current + 1}`,
+          prev: `${this.props.url}?page=${this.state.current - 1}`,
+          loading: false,
+        });
+      let first = true;
+      let last = true;
+      if (data.previous) {
+        first = false;
+      }
+      if (data.next) {
+        last = false;
+      }
+      this.setState({first, last});
+    }, error => error.then((r) => {
+      this.modalAlert.open(this.props.error, r.detail);
+      this.setState({loading: false});
+    }));
+  };
+
+  handleSearchChange(e) {
+    this.setState({ search: e.target.value });
+    if (e.target.value === '') {
+      this.setState({
+        items: [],
+        current: 1,
+        next: '',
+        prev: '',
+        url: this.props.url,
+        loading: true,
+        dir: 0,
+        start: true,
+        finish: false,
+      }, function() {
+        this.getItemsData();
       });
-    let first = true;
-    let last = true;
-    if (data.previous) {
-      first = false;
-    }
-    if (data.next) {
-      last = false;
     }
-    this.setState({ first, last });
-  }, error => error.then((r) => {
-    this.modalAlert.open(this.props.error, r.detail);
-    this.setState({ loading: false });
-  }));
+  }
+
+  handleSearchSubmit() {
+    this.setState({
+      items: [],
+      current: 1,
+      next: '',
+      prev: '',
+      url: this.props.url,
+      loading: true,
+      dir: 0,
+      start: true,
+      finish: false,
+    }, function() {
+      this.getItemsData();
+    });
+  }
 
   refresh() {
     this.forceUpdate();
@@ -112,6 +160,10 @@ export default class Pagination extends React.Component {
   render = () => (
     <div>
       <Loader active={this.state.loading} />
+      <div className="search-container">
+        <input type="text" placeholder="Cari Lowongan" onChange={this.handleSearchChange} className="search-form"/>
+        <button type="submit" onClick={this.handleSearchSubmit} className="search-button">Cari</button>
+      </div>
       <ModalAlert ref={(modal) => { this.modalAlert = modal; }} />
       {!this.state.loading && this.content()}
       {!this.state.loading && this.pageMenu()}
diff --git a/core/migrations/0020_merge_20191007_0648.py b/core/migrations/0020_merge_20191007_0648.py
new file mode 100644
index 0000000000000000000000000000000000000000..3a42b13e8acad531a1666be45051b43fca0318e4
--- /dev/null
+++ b/core/migrations/0020_merge_20191007_0648.py
@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.5 on 2019-10-06 23:48
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0017_vacancy_amount'),
+        ('core', '0019_merge_20191006_0852'),
+        ('core', '0014_auto_20191004_1340'),
+    ]
+
+    operations = [
+    ]
diff --git a/core/migrations/0021_auto_20191007_0648.py b/core/migrations/0021_auto_20191007_0648.py
new file mode 100644
index 0000000000000000000000000000000000000000..743bfd3cfe7b551934a307926873f3ceb9e76ad5
--- /dev/null
+++ b/core/migrations/0021_auto_20191007_0648.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.5 on 2019-10-06 23:48
+from __future__ import unicode_literals
+
+import django.core.validators
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0020_merge_20191007_0648'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='company',
+            name='website',
+            field=models.CharField(default=b'Belum ada link website', max_length=100),
+        ),
+        migrations.AlterField(
+            model_name='student',
+            name='phone_number',
+            field=models.CharField(blank=True, db_index=True, max_length=12, null=True, validators=[django.core.validators.RegexValidator(b'^0\\d{1,11}$')]),
+        ),
+    ]
diff --git a/core/migrations/0025_merge_20191007_1810.py b/core/migrations/0025_merge_20191007_1810.py
new file mode 100644
index 0000000000000000000000000000000000000000..5619c2624abb04e45e085a015e8d8bc95eb795ac
--- /dev/null
+++ b/core/migrations/0025_merge_20191007_1810.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.5 on 2019-10-07 11:10
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0021_auto_20191007_0648'),
+        ('core', '0024_auto_20191007_1533'),
+    ]
+
+    operations = [
+    ]
diff --git a/core/migrations/0026_merge_20191008_0525.py b/core/migrations/0026_merge_20191008_0525.py
new file mode 100644
index 0000000000000000000000000000000000000000..31a03215fe2031121fa5683008856ba25469124d
--- /dev/null
+++ b/core/migrations/0026_merge_20191008_0525.py
@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.5 on 2019-10-07 22:25
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0025_merge_20191007_1810'),
+        ('core', '0025_merge_20191007_2124'),
+        ('core', '0025_merge_20191008_0048'),
+    ]
+
+    operations = [
+    ]
diff --git a/core/migrations/0027_merge_20191008_0652.py b/core/migrations/0027_merge_20191008_0652.py
new file mode 100644
index 0000000000000000000000000000000000000000..cd5f54dc9175743548528801af4f27a066c7ca5e
--- /dev/null
+++ b/core/migrations/0027_merge_20191008_0652.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.5 on 2019-10-07 23:52
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0026_merge_20191008_0525'),
+        ('core', '0026_merge_20191008_0256'),
+    ]
+
+    operations = [
+    ]
diff --git a/core/tests/test_vacancies.py b/core/tests/test_vacancies.py
index 4e37048ec406da450390a5dc6b450c133cdca3aa..668444fb09ffb8a9c37dddffec020869791b0c8b 100644
--- a/core/tests/test_vacancies.py
+++ b/core/tests/test_vacancies.py
@@ -43,6 +43,37 @@ class ApplicationTests(APITestCase):
 
         self.assertEqual(response.status_code, status.HTTP_200_OK)
 
+    @requests_mock.Mocker()
+    def test_application_search(self, m):
+        m.get('https://akun.cs.ui.ac.id/oauth/token/verify/?client_id=X3zNkFmepkdA47ASNMDZRX3Z9gqSU1Lwywu5WepG', json={"username": 'dummy.mahasiswa', "role": 'mahasiswa', "identity_number": '1234567890'}, status_code=200)
+        m.post('https://api.cs.ui.ac.id/authentication/ldap/v2/', json={
+            "username": "dummy.mahasiswa",
+            "nama": "Dummy Mahasiswa",
+            "state": 1,
+            "kode_org": "01.00.12.01:mahasiswa",
+            "kodeidentitas": "1234567890",
+            "nama_role": "mahasiswa"
+        }, status_code=200)
+        m.get('https://api.cs.ui.ac.id/siakngcs/mahasiswa/1234567890?client_id=X3zNkFmepkdA47ASNMDZRX3Z9gqSU1Lwywu5WepG', json={
+            "kota_lahir": "kota_kota",
+            "tgl_lahir": "2017-12-31",
+            "program": [{
+                "nm_org": "Ilmu Informasi",
+                "angkatan": "2017"
+            }]
+        }, status_code=200)
+
+        url = '/api/login/'
+
+        response = self.client.post(url, {'username': 'dummy.mahasiswa', 'password': 'lalala', 'login-type': 'sso-ui'},
+                                    format='json')
+        student_id = response.data.get('student').get('id')
+
+        url = '/api/students/' + str(student_id) + '/applied-vacancies/?search=engineer'
+        response = self.client.get(url)
+
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+
     @requests_mock.Mocker()
     def test_application_create_and_delete(self, m):
         m.get('https://akun.cs.ui.ac.id/oauth/token/verify/?client_id=X3zNkFmepkdA47ASNMDZRX3Z9gqSU1Lwywu5WepG', json={"username": 'dummy.mahasiswa', "role": 'mahasiswa', "identity_number": '1234567890'}, status_code=200)
@@ -152,6 +183,42 @@ class BookmarkApplicationTests(APITestCase):
 
         self.assertEqual(response.status_code, status.HTTP_200_OK)
 
+    @requests_mock.Mocker()
+    def test_search_bookmarked_application(self, m):
+        m.get('https://akun.cs.ui.ac.id/oauth/token/verify/?client_id=X3zNkFmepkdA47ASNMDZRX3Z9gqSU1Lwywu5WepG',
+              json={"username": 'dummy.mahasiswa', "role": 'mahasiswa', "identity_number": '1234567890'},
+              status_code=200)
+        m.post('https://api.cs.ui.ac.id/authentication/ldap/v2/', json={
+            "username": "dummy.mahasiswa",
+            "nama": "Dummy Mahasiswa",
+            "state": 1,
+            "kode_org": "01.00.12.01:mahasiswa",
+            "kodeidentitas": "1234567890",
+            "nama_role": "mahasiswa"
+        }, status_code=200)
+        m.get(
+            'https://api.cs.ui.ac.id/siakngcs/mahasiswa/1234567890?client_id=X3zNkFmepkdA47ASNMDZRX3Z9gqSU1Lwywu5WepG',
+            json={
+                "kota_lahir": "kota_kota",
+                "tgl_lahir": "2017-12-31",
+                "program": [{
+                    "nm_org": "Ilmu Informasi",
+                    "angkatan": "2017"
+                }]
+            }, status_code=200)
+
+        url = '/api/login/'
+
+        response = self.client.post(url,
+                                    {'username': 'dummy.mahasiswa', 'password': 'lalala', 'login-type': 'sso-ui'},
+                                    format='json')
+        student_id = response.data.get('student').get('id')
+
+        url = '/api/students/' + str(student_id) + '/bookmarked-vacancies/?search=engineer'
+        response = self.client.get(url)
+
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+
     @requests_mock.Mocker()
     def test_application_create_and_delete(self, m):
         m.get('https://akun.cs.ui.ac.id/oauth/token/verify/?client_id=X3zNkFmepkdA47ASNMDZRX3Z9gqSU1Lwywu5WepG', json={"username": 'dummy.mahasiswa', "role": 'mahasiswa', "identity_number": '1234567890'}, status_code=200)
@@ -202,6 +269,44 @@ class VacancyTest(APITestCase):
         response = self.client.get(url, format='json')
         self.assertEqual(response.status_code, status.HTTP_200_OK)
 
+    @requests_mock.Mocker()
+    def test_search_vacancy(self, m):
+        superuser = User.objects.create_user('dummy.company', 'dummy.company@company.com', 'lalala123')
+        company = Company.objects.create(user=superuser, description="This is a test company")
+        Vacancy.objects.create(company=company, open_time=datetime.now(), close_time=datetime.now(), name="Software Engineer")
+        Vacancy.objects.create(company=company, open_time=datetime.now(), close_time=datetime.now(), name="Data Engineer")
+        m.get('https://akun.cs.ui.ac.id/oauth/token/verify/?client_id=X3zNkFmepkdA47ASNMDZRX3Z9gqSU1Lwywu5WepG',
+              json={"username": 'dummy.mahasiswa', "role": 'mahasiswa', "identity_number": '1234567890'},
+              status_code=200)
+        m.post('https://api.cs.ui.ac.id/authentication/ldap/v2/', json={
+            "username": "dummy.mahasiswa",
+            "nama": "Dummy Mahasiswa",
+            "state": 1,
+            "kode_org": "01.00.12.01:mahasiswa",
+            "kodeidentitas": "1234567890",
+            "nama_role": "mahasiswa"
+        }, status_code=200)
+        m.get(
+            'https://api.cs.ui.ac.id/siakngcs/mahasiswa/1234567890?client_id=X3zNkFmepkdA47ASNMDZRX3Z9gqSU1Lwywu5WepG',
+            json={
+                "kota_lahir": "kota_kota",
+                "tgl_lahir": "2017-12-31",
+                "program": [{
+                    "nm_org": "Ilmu Informasi",
+                    "angkatan": "2017"
+                }]
+            }, status_code=200)
+
+        url = '/api/login/'
+
+        self.client.post(url, {'username': 'dummy.mahasiswa', 'password': 'lalala', 'login-type': 'sso-ui'}, format='json')
+
+        url = '/api/vacancies/?search=software'
+        response = self.client.get(url, format='json')
+        self.assertEqual(1, Company.objects.all().count())
+        self.assertEqual(2, Vacancy.objects.all().count())
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+
     def test_unverified_vacancy_list(self):
         superuser = User.objects.create_superuser('dummy.company', 'dummy.company@company.com', 'lalala123')
         self.client.force_authenticate(user=superuser)
diff --git a/core/views/vacancies.py b/core/views/vacancies.py
index e4d0d6674e3973398c3f63e7a6e5400cf7b3f494..46f79ab776bfc6a38f6aac09a77cc070d8e8c23a 100644
--- a/core/views/vacancies.py
+++ b/core/views/vacancies.py
@@ -1,6 +1,7 @@
 import requests
 from django.utils import timezone
 from django.conf import settings
+from django.db.models import Q
 from rest_framework import viewsets, status
 from rest_framework.decorators import detail_route, permission_classes
 from rest_framework.exceptions import ValidationError
@@ -37,8 +38,12 @@ class VacancyViewSet(MultiSerializerViewSetMixin, viewsets.ModelViewSet):
         return super(VacancyViewSet, self).get_permissions()
 
     def list(self, request, *args, **kwargs):
-        vacancies = Vacancy.objects.all()
         verified = request.query_params['verified'] if 'verified' in request.query_params else "True"
+        search = request.query_params['search'] if 'search' in request.query_params else None
+        if search is not None:
+            vacancies = Vacancy.objects.filter(Q(name__icontains=search) | Q(company__user__username__icontains=search))
+        else:
+            vacancies = Vacancy.objects.all()
         companies = [int(x) for x in request.query_params.getlist('company', [])]
         if verified.lower() in ("yes", "true", "t", "1"):
             vacancies = vacancies.filter(verified=True)
@@ -57,6 +62,7 @@ class VacancyViewSet(MultiSerializerViewSetMixin, viewsets.ModelViewSet):
         page = self.paginate_queryset(vacancies)
         if page is not None:
             return self.get_paginated_response(VacancySerializer(page, many=True, context={'request': request}).data)
+        vacancies = Vacancy.objects.all()
         return Response(VacancySerializer(vacancies, many=True, context={'request': request}).data)
 
     def name_position_validator(self, names):
@@ -185,7 +191,11 @@ class StudentApplicationViewSet(viewsets.GenericViewSet):
         """
         student = get_object_or_404(Student.objects.all(), pk=student_id)
         vacancy_ids = Application.objects.filter(student=student).values('vacancy')
-        vacancies = Vacancy.objects.filter(id__in=vacancy_ids)
+        search = request.query_params['search'] if 'search' in request.query_params else None
+        if search is not None:
+            vacancies = Vacancy.objects.filter(Q(id__in=vacancy_ids) & (Q(name__icontains=search) | Q(company__user__username__icontains=search)))
+        else:
+            vacancies = Vacancy.objects.filter(id__in=vacancy_ids)
         page = self.paginate_queryset(vacancies)
         if page is not None:
             return self.get_paginated_response(VacancySerializer(page, many=True, context={'request': request}).data)
@@ -355,7 +365,11 @@ class BookmarkedVacancyByStudentViewSet(viewsets.GenericViewSet):
         ---
         """
         student = get_object_or_404(Student.objects.all(), pk=student_id)
-        vacancies = student.bookmarked_vacancies.all()
+        search = request.query_params['search'] if 'search' in request.query_params else None
+        if search is not None:
+            vacancies = student.bookmarked_vacancies.filter(Q(name__icontains=search) | Q(company__user__username__icontains=search))
+        else:
+            vacancies = student.bookmarked_vacancies.all()
         page = self.paginate_queryset(vacancies)
         if page is not None:
             return self.get_paginated_response(VacancySerializer(page, many=True, context={'request': request}).data)